Kaynağa Gözat

Merge pull request #1502 from Avaiga/test/Metric-component

Adding unit test for Metric component
Nam Nguyen 10 ay önce
ebeveyn
işleme
796f4ee332

+ 312 - 11
frontend/taipy-gui/src/components/Taipy/Metric.spec.tsx

@@ -12,20 +12,321 @@
  */
 
 import React from "react";
-import {render} from "@testing-library/react";
+import { render, waitFor } from "@testing-library/react";
 import "@testing-library/jest-dom";
+import { ThemeProvider } from "@mui/material/styles";
+import { createTheme } from "@mui/material/styles";
 
 import Metric from "./Metric";
 
+const template = {
+    layout: {
+        colorscale: {
+            diverging: [
+                [0, "#8e0152"],
+                [0.1, "#c51b7d"],
+                [0.2, "#de77ae"],
+                [0.3, "#f1b6da"],
+                [0.4, "#fde0ef"],
+                [0.5, "#f7f7f7"],
+                [0.6, "#e6f5d0"],
+                [0.7, "#b8e186"],
+                [0.8, "#7fbc41"],
+                [0.9, "#4d9221"],
+                [1, "#276419"],
+            ],
+            sequential: [
+                [0, "#0d0887"],
+                [0.1111111111111111, "#46039f"],
+                [0.2222222222222222, "#7201a8"],
+                [0.3333333333333333, "#9c179e"],
+                [0.4444444444444444, "#bd3786"],
+                [0.5555555555555556, "#d8576b"],
+                [0.6666666666666666, "#ed7953"],
+                [0.7777777777777778, "#fb9f3a"],
+                [0.8888888888888888, "#fdca26"],
+                [1, "#f0f921"],
+            ],
+            sequentialminus: [
+                [0, "#0d0887"],
+                [0.1111111111111111, "#46039f"],
+                [0.2222222222222222, "#7201a8"],
+                [0.3333333333333333, "#9c179e"],
+                [0.4444444444444444, "#bd3786"],
+                [0.5555555555555556, "#d8576b"],
+                [0.6666666666666666, "#ed7953"],
+                [0.7777777777777778, "#fb9f3a"],
+                [0.8888888888888888, "#fdca26"],
+                [1, "#f0f921"],
+            ],
+        },
+        paper_bgcolor: "rgb(255,0,0)",
+    },
+};
+
+const colorMap = {
+    20: "red",
+    40: null,
+    60: "blue",
+    80: null,
+};
+
+const darkTemplate = {
+    layout: {
+        colorscale: {
+            diverging: [
+                [0, "#8e0152"],
+                [0.1, "#c51b7d"],
+                [0.2, "#de77ae"],
+                [0.3, "#f1b6da"],
+                [0.4, "#fde0ef"],
+                [0.5, "#f7f7f7"],
+                [0.6, "#e6f5d0"],
+                [0.7, "#b8e186"],
+                [0.8, "#7fbc41"],
+                [0.9, "#4d9221"],
+                [1, "#276419"],
+            ],
+            sequential: [
+                [0, "#0d0887"],
+                [0.1111111111111111, "#46039f"],
+                [0.2222222222222222, "#7201a8"],
+                [0.3333333333333333, "#9c179e"],
+                [0.4444444444444444, "#bd3786"],
+                [0.5555555555555556, "#d8576b"],
+                [0.6666666666666666, "#ed7953"],
+                [0.7777777777777778, "#fb9f3a"],
+                [0.8888888888888888, "#fdca26"],
+                [1, "#f0f921"],
+            ],
+            sequentialminus: [
+                [0, "#0d0887"],
+                [0.1111111111111111, "#46039f"],
+                [0.2222222222222222, "#7201a8"],
+                [0.3333333333333333, "#9c179e"],
+                [0.4444444444444444, "#bd3786"],
+                [0.5555555555555556, "#d8576b"],
+                [0.6666666666666666, "#ed7953"],
+                [0.7777777777777778, "#fb9f3a"],
+                [0.8888888888888888, "#fdca26"],
+                [1, "#f0f921"],
+            ],
+        },
+        paper_bgcolor: "rgb(31,47,68)",
+    },
+};
+
+const lightTemplate = {
+    layout: {
+        colorscale: {
+            diverging: [
+                [0, "#053061"],
+                [0.1, "#2166ac"],
+                [0.2, "#4393c3"],
+                [0.3, "#92c5de"],
+                [0.4, "#d1e5f0"],
+                [0.5, "#f7f7f7"],
+                [0.6, "#fddbc7"],
+                [0.7, "#f4a582"],
+                [0.8, "#d6604d"],
+                [0.9, "#b2182b"],
+                [1, "#67001f"],
+            ],
+            sequential: [
+                [0, "#f7fcf5"],
+                [0.1111111111111111, "#e5f5e0"],
+                [0.2222222222222222, "#c7e9c0"],
+                [0.3333333333333333, "#a1d99b"],
+                [0.4444444444444444, "#74c476"],
+                [0.5555555555555556, "#41ab5d"],
+                [0.6666666666666666, "#238b45"],
+                [0.7777777777777778, "#006d2c"],
+                [0.8888888888888888, "#00441b"],
+                [1, "#000000"],
+            ],
+            sequentialminus: [
+                [0, "#f7fcf5"],
+                [0.1111111111111111, "#e5f5e0"],
+                [0.2222222222222222, "#c7e9c0"],
+                [0.3333333333333333, "#a1d99b"],
+                [0.4444444444444444, "#74c476"],
+                [0.5555555555555556, "#41ab5d"],
+                [0.6666666666666666, "#238b45"],
+                [0.7777777777777778, "#006d2c"],
+                [0.8888888888888888, "#00441b"],
+                [1, "#000000"],
+            ],
+        },
+        paper_bgcolor: "rgb(255,255,255)",
+    },
+};
+
 describe("Metric Component", () => {
-  it("renders", async () => {
-    const { getByTestId } = render(<Metric testId="test-id"/>);
-    const elt = getByTestId("test-id");
-    expect(elt.tagName).toBe("DIV");
-  })
-  it("displays the right info for class", async () => {
-    const { getByTestId } = render(<Metric testId="test-id" className={'taipy-gauge'}/>);
-    const elt = getByTestId('test-id');
-    expect(elt).toHaveClass('taipy-gauge');
-  })
+    it("renders", async () => {
+        const { getByTestId } = render(<Metric testId="test-id" />);
+        const elt = getByTestId("test-id");
+        expect(elt.tagName).toBe("DIV");
+    });
+
+    it("displays the right info for class", async () => {
+        const { getByTestId } = render(<Metric testId="test-id" className={"taipy-gauge"} />);
+        const elt = getByTestId("test-id");
+        expect(elt).toHaveClass("taipy-gauge");
+    });
+
+    it("sets the title when provided", async () => {
+        const title = "Test Title";
+        const { container } = render(<Metric title={title} />);
+        await waitFor(() => {
+            const titleElement = container.querySelector(".gtitle");
+            if (!titleElement) {
+                throw new Error("Title element not found");
+            }
+            expect(titleElement.textContent).toContain(title);
+        });
+    });
+
+    it("logs an error when template prop is a malformed JSON string", () => {
+        const consoleSpy = jest.spyOn(console, "info");
+        const malformedJson = "{ key: 'value'";
+        render(<Metric template={malformedJson} />);
+        expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Error while parsing Metric.template"));
+        consoleSpy.mockRestore();
+    });
+
+    it("logs an error when colorMap prop is a malformed JSON string", () => {
+        const consoleSpy = jest.spyOn(console, "info");
+        const malformedJson = "{ key: 'value'"; // missing closing brace
+        render(<Metric colorMap={malformedJson} />);
+        expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Error parsing color_map value (metric)"));
+        consoleSpy.mockRestore();
+    });
+
+    it("sets the template when provided", async () => {
+        render(<Metric template={JSON.stringify(template)} />);
+        await waitFor(() => {
+            const elt = document.querySelector(".main-svg");
+            expect(elt).toHaveStyle({
+                backgroundColor: "rgb(255, 0, 0)",
+            });
+        });
+    });
+
+    it("processes colorMap prop correctly", async () => {
+        render(<Metric colorMap={JSON.stringify(colorMap)} />);
+        await waitFor(() => {
+            const elts = document.querySelectorAll(".bg-arc");
+            const redElt = Array.from(elts[1].children);
+            const redEltHasRedFill = redElt.some((elt) => (elt as HTMLElement).style.fill === "rgb(255, 0, 0)");
+            expect(redEltHasRedFill).toBeTruthy();
+
+            const blueElt = Array.from(elts[2].children);
+            const blueEltHasBlueFill = blueElt.some((elt) => (elt as HTMLElement).style.fill === "rgb(0, 0, 255)");
+            expect(blueEltHasBlueFill).toBeTruthy();
+        });
+    });
+
+    it("processes delta prop correctly when delta is defined", async () => {
+        render(<Metric delta={10} testId="test-id" />);
+        await waitFor(() => {
+            const elt = document.querySelector(".delta");
+            if (elt) {
+                expect(elt.textContent).toContain("10");
+            } else {
+                throw new Error("Element with class .delta not found");
+            }
+        });
+    });
+
+    it("processes type and threshold props correctly when type is linear", async () => {
+        render(<Metric type="linear" threshold={50} testId="test-id" />);
+        await waitFor(() => {
+            const elt = document.querySelector(".bullet");
+            expect(elt).toBeInTheDocument();
+        });
+    });
+
+    it("processes type and threshold props correctly when type is not linear", async () => {
+        render(<Metric type="angular" threshold={50} testId="test-id" />);
+        await waitFor(() => {
+            const elt = document.querySelector(".angular");
+            expect(elt).toBeInTheDocument();
+        });
+    });
+
+    it("applies style correctly when height is undefined", async () => {
+        render(<Metric testId="test-id" />);
+        await waitFor(() => {
+            const elt = document.querySelector(".js-plotly-plot");
+            expect(elt).toHaveStyle({
+                width: "100%",
+                position: "relative",
+                display: "inline-block",
+            });
+        });
+    });
+
+    it("processes type prop correctly when type is none", async () => {
+        render(<Metric type="none" testId="test-id" />);
+        await waitFor(() => {
+            const angularElm = document.querySelector(".angular");
+            const angularAxis = document.querySelector(".angularaxis");
+            expect(angularElm).not.toBeInTheDocument();
+            expect(angularAxis).not.toBeInTheDocument();
+        });
+    });
+
+    it("processes template_Dark_ prop correctly when theme is dark", async () => {
+        const darkTheme = createTheme({
+            palette: {
+                mode: "dark",
+            },
+        });
+
+        render(
+            <ThemeProvider theme={darkTheme}>
+                <Metric template_Dark_={JSON.stringify(darkTemplate)} testId="test-id" />
+            </ThemeProvider>,
+        );
+        await waitFor(() => {
+            const elt = document.querySelector(".main-svg");
+            expect(elt).toHaveStyle({
+                backgroundColor: "rgb(31, 47, 68)",
+            });
+        });
+    });
+
+    it("processes template_Light_ prop correctly when theme is not dark", async () => {
+        const lightTheme = createTheme({
+            palette: {
+                mode: "light",
+            },
+        });
+
+        render(
+            <ThemeProvider theme={lightTheme}>
+                <Metric template_Light_={JSON.stringify(lightTemplate)} testId="test-id" />
+            </ThemeProvider>,
+        );
+        await waitFor(() => {
+            const elt = document.querySelector(".main-svg");
+            expect(elt).toHaveStyle({
+                backgroundColor: "rgb(255, 255, 255)",
+            });
+        });
+    });
+
+    it.skip("logs an error when template_Dark_ prop is not a valid JSON string", () => {
+        const consoleSpy = jest.spyOn(console, "info");
+        render(<Metric template_Dark_="not a valid JSON string" testId="test-id" />);
+        expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Error while parsing Metric.template"));
+        consoleSpy.mockRestore();
+    }); // TODO: Not working at the moment, need to fix
+
+    it("logs an error when template_Light_ prop is not a valid JSON string", () => {
+        const consoleSpy = jest.spyOn(console, "info");
+        render(<Metric template_Light_="not a valid JSON string" testId="test-id" />);
+        expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Error while parsing Metric.template"));
+        consoleSpy.mockRestore();
+    });
 });