UNPKG

@netdata/charts

Version:

Netdata frontend SDK and chart utilities

701 lines (700 loc) 27.3 kB
"use strict"; var _makeDimensions = _interopRequireDefault(require("./makeDimensions")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; } function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } describe("makeDimensions", function () { var mockChart; var mockSdk; beforeEach(function () { mockChart = { getAttribute: jest.fn(), setAttribute: jest.fn(), updateAttribute: jest.fn(), trigger: jest.fn(), onAttributeChange: jest.fn(), getAttributes: jest.fn(function () { return { colors: [], contextScope: ["test"], id: "test-chart", groupBy: [], context: "system.cpu", dimensionsSort: "default", selectedLegendDimensions: [], dimensionIds: ["cpu", "memory"], selectedDimensions: ["cpu"], viewDimensions: { ids: ["cpu", "memory"], names: ["CPU Usage", "Memory Usage"], priorities: [1, 2], units: ["percentage", "bytes"], contexts: ["cpu", "memory"], grouped: [] }, sparkline: false, heatmapType: null, units: ["percentage", "bytes"], unitsConversionBase: [1000, 1000], unitsConversionPrefix: ["", ""], unitsConversionMethod: ["fixed", "fixed"], unitsConversionFractionDigits: [2, 2], unitsConversionDivider: [1, 1], unitsByContext: {} }; }), getThemeIndex: jest.fn(function () { return 0; }), getPayload: jest.fn(function () { return { data: [[1000, 10, 20], [2000, 15, 25]], all: [[1000, 10, 20], [2000, 15, 25]] }; }), getDimensionValue: jest.fn(function () { return 50; }), getVisibleDimensionIds: jest.fn(function () { return ["cpu", "memory"]; }), getDimensionIds: jest.fn(function () { return ["cpu", "memory"]; }), isDimensionVisible: jest.fn(function () { return true; }) }; mockSdk = { getRoot: jest.fn(function () { return { getNextColor: jest.fn(function () { return "#ff0000"; }) }; }) }; (0, _makeDimensions["default"])(mockChart, mockSdk); }); it("adds isSparkline method to chart", function () { expect(_typeof(mockChart.isSparkline)).toBe("function"); }); it("adds getHeatmapType method to chart", function () { expect(_typeof(mockChart.getHeatmapType)).toBe("function"); }); it("adds getPayloadDimensionIds method to chart", function () { expect(_typeof(mockChart.getPayloadDimensionIds)).toBe("function"); }); it("returns sparkline dimensions when sparkline is true", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "sparkline") return true; return null; }); var result = mockChart.getPayloadDimensionIds(); expect(result).toEqual(["sum"]); }); it("returns viewDimensions ids when not sparkline", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "sparkline") return false; if (key === "viewDimensions") return { ids: ["cpu", "memory"] }; return null; }); var result = mockChart.getPayloadDimensionIds(); expect(result).toEqual(["cpu", "memory"]); }); it("adds getDimensionIndex method", function () { expect(_typeof(mockChart.getDimensionIndex)).toBe("function"); }); it("adds getDimensionIds method", function () { expect(_typeof(mockChart.getDimensionIds)).toBe("function"); }); it("adds getVisibleDimensionIds method", function () { expect(_typeof(mockChart.getVisibleDimensionIds)).toBe("function"); }); it("adds isDimensionVisible method", function () { expect(_typeof(mockChart.isDimensionVisible)).toBe("function"); }); it("adds getDimensionName method", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "viewDimensions") return { names: ["CPU Usage", "Memory Usage"] }; return null; }); expect(_typeof(mockChart.getDimensionName)).toBe("function"); var result = mockChart.getDimensionName("cpu"); expect(result).toBe("cpu"); }); it("adds getDimensionPriority method", function () { expect(_typeof(mockChart.getDimensionPriority)).toBe("function"); var result = mockChart.getDimensionPriority("cpu"); expect(result).toBe(0); }); it("adds getDimensionUnit method", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "viewDimensions") return { units: ["percentage", "bytes"] }; return null; }); expect(_typeof(mockChart.getDimensionUnit)).toBe("function"); var result = mockChart.getDimensionUnit(); expect(result).toBe("percentage"); }); it("adds selectDimensionColor method", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "colors") return []; if (key === "selectedDimensions") return ["cpu"]; return null; }); expect(_typeof(mockChart.selectDimensionColor)).toBe("function"); var result = mockChart.selectDimensionColor("cpu"); expect(result).toBe("#ff0000"); }); it("adds updateDimensions method", function () { expect(_typeof(mockChart.updateDimensions)).toBe("function"); }); it("adds sortDimensions method", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "dimensionsSort") return "nameAsc"; if (key === "selectedLegendDimensions") return []; return null; }); expect(_typeof(mockChart.sortDimensions)).toBe("function"); expect(function () { return mockChart.sortDimensions(); }).not.toThrow(); }); it("adds getDimensionValue method", function () { expect(_typeof(mockChart.getDimensionValue)).toBe("function"); }); it("adds toggleDimensionId method", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "selectedLegendDimensions") return []; return null; }); expect(_typeof(mockChart.toggleDimensionId)).toBe("function"); expect(function () { return mockChart.toggleDimensionId("cpu"); }).not.toThrow(); }); describe("sorting methods", function () { beforeEach(function () { mockChart.getDimensionName = jest.fn(function (id) { return id === "cpu" ? "CPU Usage" : "Memory Usage"; }); mockChart.getDimensionPriority = jest.fn(function (id) { return id === "cpu" ? 1 : 2; }); }); it("sorts by default method using priority", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "dimensionsSort") return "default"; if (key === "selectedLegendDimensions") return []; return null; }); expect(function () { return mockChart.sortDimensions(); }).not.toThrow(); expect(mockChart.trigger).toHaveBeenCalledWith("dimensionChanged"); }); it("sorts by name ascending", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "dimensionsSort") return "nameAsc"; if (key === "selectedLegendDimensions") return []; return null; }); expect(function () { return mockChart.sortDimensions(); }).not.toThrow(); }); it("sorts by name descending", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "dimensionsSort") return "nameDesc"; if (key === "selectedLegendDimensions") return []; return null; }); expect(function () { return mockChart.sortDimensions(); }).not.toThrow(); }); it("sorts by value descending", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "dimensionsSort") return "valueDesc"; if (key === "selectedLegendDimensions") return []; return null; }); expect(function () { return mockChart.sortDimensions(); }).not.toThrow(); }); it("sorts by value ascending", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "dimensionsSort") return "valueAsc"; if (key === "selectedLegendDimensions") return []; return null; }); expect(function () { return mockChart.sortDimensions(); }).not.toThrow(); }); it("sorts by anomaly descending", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "dimensionsSort") return "anomalyDesc"; if (key === "selectedLegendDimensions") return []; return null; }); expect(function () { return mockChart.sortDimensions(); }).not.toThrow(); }); it("sorts by anomaly ascending", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "dimensionsSort") return "anomalyAsc"; if (key === "selectedLegendDimensions") return []; return null; }); expect(function () { return mockChart.sortDimensions(); }).not.toThrow(); }); it("sorts by annotations descending", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "dimensionsSort") return "annotationsDesc"; if (key === "selectedLegendDimensions") return []; return null; }); expect(function () { return mockChart.sortDimensions(); }).not.toThrow(); }); it("sorts by annotations ascending", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "dimensionsSort") return "annotationsAsc"; if (key === "selectedLegendDimensions") return []; return null; }); expect(function () { return mockChart.sortDimensions(); }).not.toThrow(); }); it("uses default sort for unknown method", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "dimensionsSort") return "unknownSort"; if (key === "selectedLegendDimensions") return []; return null; }); expect(function () { return mockChart.sortDimensions(); }).not.toThrow(); }); }); describe("dimension visibility", function () { it("filters visible dimensions when selectedLegendDimensions has values", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "selectedLegendDimensions") return ["cpu"]; if (key === "dimensionsSort") return "default"; return null; }); mockChart.getDimensionName = jest.fn(function (id) { return id === "cpu" ? "CPU Usage" : "Memory Usage"; }); mockChart.sortDimensions(); expect(mockChart.trigger).toHaveBeenCalledWith("dimensionChanged"); }); it("shows all dimensions when selectedLegendDimensions is empty", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "selectedLegendDimensions") return []; if (key === "dimensionsSort") return "default"; return null; }); mockChart.sortDimensions(); expect(mockChart.trigger).toHaveBeenCalledWith("dimensionChanged"); }); it("includes dimensions by name in selectedLegendDimensions", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "selectedLegendDimensions") return ["CPU Usage"]; if (key === "dimensionsSort") return "default"; return null; }); mockChart.getDimensionName = jest.fn(function (id) { return id === "cpu" ? "CPU Usage" : "Memory Usage"; }); mockChart.sortDimensions(); expect(mockChart.trigger).toHaveBeenCalledWith("dimensionChanged"); }); }); describe("color selection", function () { it("returns color from colors attribute for sparkline", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "sparkline") return true; if (key === "colors") return ["#blue"]; return null; }); var color = mockChart.selectDimensionColor("cpu"); expect(color).toBe("#blue"); }); it("returns color for selected dimension", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "sparkline") return false; if (key === "colors") return ["#green"]; if (key === "selectedDimensions") return ["cpu"]; return null; }); var color = mockChart.selectDimensionColor("selected"); expect(color).toBe("#green"); }); it("uses SDK color when no colors attribute", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "sparkline") return false; if (key === "colors") return []; if (key === "selectedDimensions") return ["cpu"]; return null; }); var color = mockChart.selectDimensionColor("cpu"); expect(color).toBe("#ff0000"); }); it("handles partIndex for split dimension names", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "sparkline") return false; if (key === "colors") return []; if (key === "selectedDimensions") return ["cpu,gpu"]; return null; }); var color = mockChart.selectDimensionColor("cpu,gpu", 1); expect(color).toBe("#ff0000"); }); }); describe("dimension names and properties", function () { it("returns dimension name with partIndex", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "viewDimensions") return { names: ["CPU,GPU Usage"] }; return null; }); var name = mockChart.getDimensionName("cpu", 0); expect(name).toBe("cpu"); }); it("returns empty string when no viewDimensions names", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "viewDimensions") return {}; return null; }); var name = mockChart.getDimensionName("cpu"); expect(name).toBe(""); }); it("returns 0 priority when no viewDimensions priorities", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "viewDimensions") return {}; return null; }); var priority = mockChart.getDimensionPriority("cpu"); expect(priority).toBe(0); }); it("returns first unit when no id provided", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "viewDimensions") return { units: ["percentage", "bytes"] }; return null; }); var unit = mockChart.getDimensionUnit(); expect(unit).toBe("percentage"); }); it("returns empty string when no viewDimensions units", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "viewDimensions") return {}; return null; }); var unit = mockChart.getDimensionUnit("cpu"); expect(unit).toBe(""); }); }); describe("heatmap type detection", function () { it("sets heatmap type for grouped by dimension with matching prefix", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "groupBy") return ["dimension"]; if (key === "context") return "system.cpu"; if (key === "dimensionsSort") return "default"; if (key === "selectedLegendDimensions") return []; if (key === "dimensionIds") return ["cpu_0", "cpu_1", "cpu_2"]; return null; }); var dimensionIds = ["cpu_0", "cpu_1", "cpu_2"]; mockChart.getPayloadDimensionIds = jest.fn(function () { return dimensionIds; }); mockChart.updateDimensions(); expect(mockChart.setAttribute).toHaveBeenCalled(); }); it("disables heatmap for mixed prefixes", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "groupBy") return ["dimension"]; if (key === "context") return "system.cpu"; if (key === "dimensionsSort") return "default"; if (key === "selectedLegendDimensions") return []; if (key === "dimensionIds") return ["cpu_0", "memory_1"]; return null; }); var dimensionIds = ["cpu_0", "memory_1"]; mockChart.getPayloadDimensionIds = jest.fn(function () { return dimensionIds; }); mockChart.updateDimensions(); expect(mockChart.setAttribute).toHaveBeenCalled(); }); it("sets default heatmap type for latency context", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "groupBy") return ["dimension"]; if (key === "context") return "system.latency"; if (key === "dimensionsSort") return "default"; if (key === "selectedLegendDimensions") return []; if (key === "dimensionIds") return ["latency_0", "latency_1"]; return null; }); var dimensionIds = ["latency_0", "latency_1"]; mockChart.getPayloadDimensionIds = jest.fn(function () { return dimensionIds; }); mockChart.updateDimensions(); expect(mockChart.setAttribute).toHaveBeenCalled(); }); it("sets null heatmap type when not grouped by dimension", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "groupBy") return ["instance"]; if (key === "dimensionsSort") return "default"; if (key === "selectedLegendDimensions") return []; if (key === "dimensionIds") return ["cpu", "memory"]; return null; }); var dimensionIds = ["cpu", "memory"]; mockChart.getPayloadDimensionIds = jest.fn(function () { return dimensionIds; }); mockChart.updateDimensions(); expect(mockChart.setAttribute).toHaveBeenCalledWith("heatmapType", null); }); }); describe("toggleDimensionId advanced scenarios", function () { it("toggles dimension when selectedLegendDimensions is empty", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "selectedLegendDimensions") return []; return null; }); mockChart.getDimensionIds = jest.fn(function () { return ["cpu", "memory", "disk"]; }); mockChart.toggleDimensionId("cpu"); expect(mockChart.updateAttribute).toHaveBeenCalledWith("selectedLegendDimensions", ["cpu"]); }); it("toggles dimension with merge option when empty", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "selectedLegendDimensions") return []; return null; }); mockChart.getDimensionIds = jest.fn(function () { return ["cpu", "memory", "disk"]; }); mockChart.toggleDimensionId("cpu", { merge: true }); expect(mockChart.updateAttribute).toHaveBeenCalledWith("selectedLegendDimensions", ["memory", "disk"]); }); it("removes visible dimension", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "selectedLegendDimensions") return ["cpu", "memory"]; return null; }); mockChart.isDimensionVisible = jest.fn(function (id) { return id === "cpu"; }); mockChart.toggleDimensionId("cpu"); expect(mockChart.updateAttribute).toHaveBeenCalledWith("selectedLegendDimensions", ["cpu"]); }); it("removes visible dimension with merge option", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "selectedLegendDimensions") return ["cpu", "memory"]; return null; }); mockChart.isDimensionVisible = jest.fn(function (id) { return id === "cpu"; }); mockChart.toggleDimensionId("cpu", { merge: true }); expect(mockChart.updateAttribute).toHaveBeenCalledWith("selectedLegendDimensions", ["memory"]); }); it("clears selection when removing last dimension", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "selectedLegendDimensions") return ["cpu"]; return null; }); mockChart.isDimensionVisible = jest.fn(function () { return true; }); mockChart.toggleDimensionId("cpu"); expect(mockChart.updateAttribute).toHaveBeenCalledWith("selectedLegendDimensions", []); }); it("adds non-visible dimension", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "selectedLegendDimensions") return ["cpu"]; return null; }); mockChart.isDimensionVisible = jest.fn(function () { return false; }); mockChart.toggleDimensionId("memory"); expect(mockChart.updateAttribute).toHaveBeenCalledWith("selectedLegendDimensions", ["memory"]); }); it("adds non-visible dimension with merge", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "selectedLegendDimensions") return ["cpu"]; return null; }); mockChart.isDimensionVisible = jest.fn(function () { return false; }); mockChart.toggleDimensionId("memory", { merge: true }); expect(mockChart.updateAttribute).toHaveBeenCalledWith("selectedLegendDimensions", ["cpu", "memory"]); }); }); describe("edge cases and additional methods", function () { it("handles getUnitAttributes with context", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "unitsByContext") return { cpu: { unit: "percentage" } }; if (key === "viewDimensions") return { contexts: ["cpu", "memory"] }; return null; }); mockChart.getDimensionContext = jest.fn(function () { return "cpu"; }); var attrs = mockChart.getUnitAttributes("cpu"); expect(attrs).toEqual({ unit: "percentage" }); }); it("handles getUnitAttributes without context", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "unitsByContext") return {}; if (key === "viewDimensions") return { units: ["percentage"], contexts: ["cpu"] }; if (key === "units") return ["percentage", "bytes"]; if (key === "unitsConversionBase") return [1000, 1000]; if (key === "unitsConversionPrefix") return ["", ""]; if (key === "unitsConversionMethod") return ["fixed", "fixed"]; if (key === "unitsConversionFractionDigits") return [2, 2]; if (key === "unitsConversionDivider") return [1, 1]; return null; }); mockChart.getDimensionContext = jest.fn(function () { return "cpu"; }); mockChart.getDimensionUnit = jest.fn(function () { return "percentage"; }); var attrs = mockChart.getUnitAttributes("cpu"); expect(attrs).toHaveProperty("method", "fixed"); }); it("handles getDimensionGroups", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "viewDimensions") return { grouped: ["group1", "group2"] }; return null; }); var groups = mockChart.getDimensionGroups(); expect(groups).toEqual(["group1", "group2"]); }); it("returns empty array for getDimensionGroups when no groups", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "viewDimensions") return {}; return null; }); var groups = mockChart.getDimensionGroups(); expect(groups).toEqual([]); }); it("handles getRowDimensionValue with incremental logic", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "heatmapType") return "incremental"; return null; }); mockChart.getDimensionIds = jest.fn(function () { return ["cpu", "memory", "disk"]; }); mockChart.isDimensionVisible = jest.fn(function () { return true; }); mockChart.getRowDimensionValue = jest.fn().mockReturnValueOnce(30).mockReturnValueOnce(10); var pointData = [1000, 10, 20, 30]; var value = mockChart.getRowDimensionValue("disk", pointData, { incrementable: true }); expect(mockChart.getRowDimensionValue).toHaveBeenCalled(); }); it("handles onHoverSortDimensions for heatmap", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "heatmapType") return "default"; if (key === "dimensionsSort") return "valueDesc"; return null; }); var sorted = mockChart.onHoverSortDimensions(1); expect(sorted).toBeDefined(); }); it("handles onHoverSortDimensions for non-heatmap", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "heatmapType") return null; if (key === "dimensionsSort") return "valueDesc"; return null; }); var sorted = mockChart.onHoverSortDimensions(1); expect(sorted).toBeDefined(); }); it("handles color selection with number color index", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "sparkline") return false; if (key === "colors") return [2, "#blue"]; if (key === "selectedDimensions") return ["cpu"]; return null; }); var color = mockChart.selectDimensionColor("cpu"); expect(color).toBe("#ff0000"); }); it("handles empty updateColors when no dimensionIds", function () { mockChart.getAttribute.mockImplementation(function (key) { if (key === "dimensionIds") return []; return null; }); expect(function () { return mockChart.updateColors(); }).not.toThrow(); }); it("handles always sort conditions", function () { var sortDimensionsSpy = jest.spyOn(mockChart, "sortDimensions"); mockChart.getAttribute.mockImplementation(function (key) { if (key === "dimensionsSort") return "valueDesc"; if (key === "selectedLegendDimensions") return []; if (key === "groupBy") return []; if (key === "dimensionIds") return ["cpu", "memory"]; return null; }); var originalIds = ["cpu", "memory"]; mockChart.getPayloadDimensionIds = jest.fn(function () { return originalIds; }); mockChart.updateDimensions(); expect(sortDimensionsSpy).toHaveBeenCalled(); }); }); });