123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462 |
- /*
- * Copyright 2021-2024 Avaiga Private Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
- * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- */
- import React from "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 { container } = render(<Metric className="test" />);
- const elt = container.querySelector(".test");
- expect(elt?.tagName).toBe("DIV");
- });
- it("displays the right info for class", async () => {
- const { container } = render(<Metric className="test" />);
- const elt = container.querySelector(".test");
- expect(elt).toHaveClass("test");
- });
- 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 () => {
- const { container } = render(<Metric template={JSON.stringify(template)} />);
- await waitFor(() => {
- const elt = container.querySelector(".main-svg");
- expect(elt).toHaveStyle({
- backgroundColor: "rgb(255, 0, 0)",
- });
- });
- });
- it("processes colorMap prop correctly", async () => {
- const { container } = render(<Metric colorMap={JSON.stringify(colorMap)} />);
- await waitFor(() => {
- const elements = container.querySelectorAll(".bg-arc");
- const redElt = Array.from(elements[1].children);
- const redEltHasRedFill = redElt.some((elt) => (elt as HTMLElement).style.fill === "rgb(255, 0, 0)");
- expect(redEltHasRedFill).toBeTruthy();
- const blueElt = Array.from(elements[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 () => {
- const { container } = render(<Metric delta={10} />);
- await waitFor(() => {
- const elt = container.querySelector(".delta");
- if (elt) {
- expect(elt.textContent).toContain("10");
- } else {
- throw new Error("Element with class .delta not found");
- }
- });
- });
- it("applies style correctly when deltaColor is set", async () => {
- const { container } = render(<Metric delta={10} deltaColor="#FF4136" />);
- await waitFor(() => {
- const elt = container.querySelector(".delta");
- expect(elt).toHaveStyle({
- fill: "rgb(255, 65, 54)",
- });
- });
- });
- it("applies style correctly when deltaColor is set invert", async () => {
- const { container } = render(<Metric delta={10} deltaColor="invert" />);
- await waitFor(() => {
- const elt = container.querySelector(".delta");
- expect(elt).toHaveStyle({
- fill: "rgb(255, 65, 54)",
- });
- });
- });
- it("processes type and threshold props correctly when type is linear", async () => {
- const { container } = render(<Metric type="linear" threshold={50} />);
- await waitFor(() => {
- const elt = container.querySelector(".bullet");
- expect(elt).toBeInTheDocument();
- });
- });
- it("processes type and threshold props correctly when type is not linear", async () => {
- const { container } = render(<Metric type="angular" threshold={50} />);
- await waitFor(() => {
- const elt = container.querySelector(".angular");
- expect(elt).toBeInTheDocument();
- });
- });
- it("applies style correctly when height and width are undefined", async () => {
- const { container } = render(<Metric />);
- await waitFor(() => {
- const elt = container.querySelector(".js-plotly-plot");
- expect(elt).toHaveStyle({
- width: "20vw",
- height: "20vh",
- });
- });
- });
- it("applies style correctly when height is set to 100px", async () => {
- const { container } = render(<Metric height="100px" />);
- await waitFor(() => {
- const elt = container.querySelector(".js-plotly-plot");
- expect(elt).toHaveStyle({
- height: "100px",
- });
- });
- });
- it("applies style correctly when height is set to 30em", async () => {
- const { container } = render(<Metric height="30em" />);
- await waitFor(() => {
- const elt = container.querySelector(".js-plotly-plot");
- expect(elt).toHaveStyle({
- height: "30em",
- });
- });
- });
- it("applies style correctly when height is set to 30%", async () => {
- const { container } = render(<Metric height="30%" />);
- await waitFor(() => {
- const elt = container.querySelector(".js-plotly-plot");
- expect(elt).toHaveStyle({
- height: "30%",
- });
- });
- });
- it("applies style correctly when height is set to 30vh", async () => {
- const { container } = render(<Metric height="30vh" />);
- await waitFor(() => {
- const elt = container.querySelector(".js-plotly-plot");
- expect(elt).toHaveStyle({
- height: "30vh",
- });
- });
- });
- it("applies style correctly when height is set to 30vw", async () => {
- const { container } = render(<Metric height="30vw" />);
- await waitFor(() => {
- const elt = container.querySelector(".js-plotly-plot");
- expect(elt).toHaveStyle({
- height: "30vw",
- });
- });
- });
- it("applies style correctly when width is set to 100px", async () => {
- const { container } = render(<Metric width="100px" />);
- await waitFor(() => {
- const elt = container.querySelector(".js-plotly-plot");
- expect(elt).toHaveStyle({
- width: "100px",
- });
- });
- });
- it("applies style correctly when width is set to 30em", async () => {
- const { container } = render(<Metric width="30em" />);
- await waitFor(() => {
- const elt = container.querySelector(".js-plotly-plot");
- expect(elt).toHaveStyle({
- width: "30em",
- });
- });
- });
- it("applies style correctly when width is set to 30%", async () => {
- const { container } = render(<Metric width="30%" />);
- await waitFor(() => {
- const elt = container.querySelector(".js-plotly-plot");
- expect(elt).toHaveStyle({
- width: "30%",
- });
- });
- });
- it("applies style correctly when width is set to 30vh", async () => {
- const { container } = render(<Metric width="30vh" />);
- await waitFor(() => {
- const elt = container.querySelector(".js-plotly-plot");
- expect(elt).toHaveStyle({
- width: "30vh",
- });
- });
- });
- it("applies style correctly when width is set to 30vw", async () => {
- const { container } = render(<Metric width="30vw" />);
- await waitFor(() => {
- const elt = container.querySelector(".js-plotly-plot");
- expect(elt).toHaveStyle({
- width: "30vw",
- });
- });
- });
- it("processes type prop correctly when type is none (string)", async () => {
- const { container } = render(<Metric type="none" />);
- await waitFor(() => {
- const angularElm = container.querySelector(".angular");
- const angularAxis = container.querySelector(".angularaxis");
- expect(angularElm).not.toBeInTheDocument();
- expect(angularAxis).not.toBeInTheDocument();
- });
- });
- it("processes type prop correctly when type is None", async () => {
- const { container } = render(<Metric type="None" />);
- await waitFor(() => {
- const angularElm = container.querySelector(".angular");
- const angularAxis = container.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",
- },
- });
- const { container } = render(
- <ThemeProvider theme={darkTheme}>
- <Metric template_Dark_={JSON.stringify(darkTemplate)} />
- </ThemeProvider>,
- );
- await waitFor(() => {
- const elt = container.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",
- },
- });
- const { container } = render(
- <ThemeProvider theme={lightTheme}>
- <Metric template_Light_={JSON.stringify(lightTemplate)} />
- </ThemeProvider>,
- );
- await waitFor(() => {
- const elt = container.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" />);
- 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" />);
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining("Error while parsing Metric.template"));
- consoleSpy.mockRestore();
- });
- });
|