|
@@ -12,191 +12,41 @@
|
|
|
*/
|
|
|
|
|
|
import React from "react";
|
|
|
-import { render, screen, waitFor } from "@testing-library/react";
|
|
|
+import { render } from "@testing-library/react";
|
|
|
import "@testing-library/jest-dom";
|
|
|
-import { SnackbarProvider } from "notistack";
|
|
|
+import TaipyAlert from "./Alert";
|
|
|
|
|
|
-import Alert from "./Alert";
|
|
|
-import { AlertMessage } from "../../context/taipyReducers";
|
|
|
-import userEvent from "@testing-library/user-event";
|
|
|
-
|
|
|
-const defaultMessage = "message";
|
|
|
-const defaultAlerts: AlertMessage[] = [{ atype: "success", message: defaultMessage, system: true, duration: 3000 }];
|
|
|
-const getAlertsWithType = (aType: string) => [{ ...defaultAlerts[0], atype: aType }];
|
|
|
-
|
|
|
-class myNotification {
|
|
|
- static requestPermission = jest.fn(() => Promise.resolve("granted"));
|
|
|
- static permission = "granted";
|
|
|
-}
|
|
|
-
|
|
|
-describe("Alert Component", () => {
|
|
|
- beforeAll(() => {
|
|
|
- globalThis.Notification = myNotification as unknown as jest.Mocked<typeof Notification>;
|
|
|
- });
|
|
|
- beforeEach(() => {
|
|
|
- jest.clearAllMocks();
|
|
|
- });
|
|
|
- it("renders", async () => {
|
|
|
- const { getByText } = render(
|
|
|
- <SnackbarProvider>
|
|
|
- <Alert alerts={defaultAlerts} />
|
|
|
- </SnackbarProvider>,
|
|
|
- );
|
|
|
- const elt = getByText(defaultMessage);
|
|
|
- expect(elt.tagName).toBe("DIV");
|
|
|
- });
|
|
|
- it("displays a success alert", async () => {
|
|
|
- const { getByText } = render(
|
|
|
- <SnackbarProvider>
|
|
|
- <Alert alerts={defaultAlerts} />
|
|
|
- </SnackbarProvider>,
|
|
|
- );
|
|
|
- const elt = getByText(defaultMessage);
|
|
|
- expect(elt.closest(".notistack-MuiContent-success")).toBeInTheDocument();
|
|
|
- });
|
|
|
- it("displays an error alert", async () => {
|
|
|
- const { getByText } = render(
|
|
|
- <SnackbarProvider>
|
|
|
- <Alert alerts={getAlertsWithType("error")} />
|
|
|
- </SnackbarProvider>,
|
|
|
- );
|
|
|
- const elt = getByText(defaultMessage);
|
|
|
- expect(elt.closest(".notistack-MuiContent-error")).toBeInTheDocument();
|
|
|
- });
|
|
|
- it("displays a warning alert", async () => {
|
|
|
- const { getByText } = render(
|
|
|
- <SnackbarProvider>
|
|
|
- <Alert alerts={getAlertsWithType("warning")} />
|
|
|
- </SnackbarProvider>,
|
|
|
- );
|
|
|
- const elt = getByText(defaultMessage);
|
|
|
- expect(elt.closest(".notistack-MuiContent-warning")).toBeInTheDocument();
|
|
|
- });
|
|
|
- it("displays an info alert", async () => {
|
|
|
- const { getByText } = render(
|
|
|
- <SnackbarProvider>
|
|
|
- <Alert alerts={getAlertsWithType("info")} />
|
|
|
- </SnackbarProvider>,
|
|
|
- );
|
|
|
- const elt = getByText(defaultMessage);
|
|
|
- expect(elt.closest(".notistack-MuiContent-info")).toBeInTheDocument();
|
|
|
- });
|
|
|
- it("gets favicon URL from document link tags", () => {
|
|
|
- const link = document.createElement("link");
|
|
|
- link.rel = "icon";
|
|
|
- link.href = "/test-icon.png";
|
|
|
- document.head.appendChild(link);
|
|
|
- const alerts: AlertMessage[] = [
|
|
|
- { atype: "success", message: "This is a system alert", system: true, duration: 3000 },
|
|
|
- ];
|
|
|
- render(
|
|
|
- <SnackbarProvider>
|
|
|
- <Alert alerts={alerts} />
|
|
|
- </SnackbarProvider>,
|
|
|
- );
|
|
|
- const linkElement = document.querySelector("link[rel='icon']");
|
|
|
- if (linkElement) {
|
|
|
- expect(linkElement.getAttribute("href")).toBe("/test-icon.png");
|
|
|
- } else {
|
|
|
- expect(true).toBe(false);
|
|
|
- }
|
|
|
- document.head.removeChild(link);
|
|
|
- });
|
|
|
-
|
|
|
- it("closes alert on close button click", async () => {
|
|
|
- const alerts = [{ atype: "success", message: "Test Alert", duration: 3000, system: false }];
|
|
|
- render(
|
|
|
- <SnackbarProvider>
|
|
|
- <Alert alerts={alerts} />
|
|
|
- </SnackbarProvider>,
|
|
|
- );
|
|
|
- const closeButton = await screen.findByRole("button", { name: /close/i });
|
|
|
- await userEvent.click(closeButton);
|
|
|
- await waitFor(() => {
|
|
|
- const alertMessage = screen.queryByText("Test Alert");
|
|
|
- expect(alertMessage).not.toBeInTheDocument();
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- it("Alert disappears when alert type is empty", async () => {
|
|
|
- const alerts = [{ atype: "success", message: "Test Alert", duration: 3000, system: false }];
|
|
|
- const { rerender } = render(
|
|
|
- <SnackbarProvider>
|
|
|
- <Alert alerts={alerts} />
|
|
|
- </SnackbarProvider>,
|
|
|
- );
|
|
|
- await screen.findByRole("button", { name: /close/i });
|
|
|
- const newAlerts = [{ atype: "", message: "Test Alert", duration: 3000, system: false }];
|
|
|
- rerender(
|
|
|
- <SnackbarProvider>
|
|
|
- <Alert alerts={newAlerts} />
|
|
|
- </SnackbarProvider>,
|
|
|
- );
|
|
|
- await waitFor(() => {
|
|
|
- const alertMessage = screen.queryByText("Test Alert");
|
|
|
- expect(alertMessage).not.toBeInTheDocument();
|
|
|
- });
|
|
|
+describe("TaipyAlert Component", () => {
|
|
|
+ it("renders with default properties", () => {
|
|
|
+ const { getByRole } = render(<TaipyAlert message="Default Alert" />);
|
|
|
+ const alert = getByRole("alert");
|
|
|
+ expect(alert).toBeInTheDocument();
|
|
|
+ expect(alert).toHaveClass("MuiAlert-filledError");
|
|
|
});
|
|
|
|
|
|
- it("does nothing when alert is undefined", async () => {
|
|
|
- render(
|
|
|
- <SnackbarProvider>
|
|
|
- <Alert alerts={[]} />
|
|
|
- </SnackbarProvider>,
|
|
|
- );
|
|
|
- expect(Notification.requestPermission).not.toHaveBeenCalled();
|
|
|
+ it("applies the correct severity", () => {
|
|
|
+ const { getByRole } = render(<TaipyAlert message="Warning Alert" severity="warning" />);
|
|
|
+ const alert = getByRole("alert");
|
|
|
+ expect(alert).toBeInTheDocument();
|
|
|
+ expect(alert).toHaveClass("MuiAlert-filledWarning");
|
|
|
});
|
|
|
|
|
|
- it("validates href when rel attribute is 'icon' and href is set", () => {
|
|
|
- const link = document.createElement("link");
|
|
|
- link.rel = "icon";
|
|
|
- link.href = "/test-icon.png";
|
|
|
- document.head.appendChild(link);
|
|
|
- const alerts: AlertMessage[] = [
|
|
|
- { atype: "success", message: "This is a system alert", system: true, duration: 3000 },
|
|
|
- ];
|
|
|
- render(
|
|
|
- <SnackbarProvider>
|
|
|
- <Alert alerts={alerts} />
|
|
|
- </SnackbarProvider>,
|
|
|
- );
|
|
|
- const linkElement = document.querySelector("link[rel='icon']");
|
|
|
- expect(linkElement?.getAttribute("href")).toBe("/test-icon.png");
|
|
|
- document.head.removeChild(link);
|
|
|
+ it("applies the correct variant", () => {
|
|
|
+ const { getByRole } = render(<TaipyAlert message="Outlined Alert" variant="outlined" />);
|
|
|
+ const alert = getByRole("alert");
|
|
|
+ expect(alert).toBeInTheDocument();
|
|
|
+ expect(alert).toHaveClass("MuiAlert-outlinedError");
|
|
|
});
|
|
|
|
|
|
- it("verifies default favicon for 'icon' rel attribute when href is unset/empty", () => {
|
|
|
- const link = document.createElement("link");
|
|
|
- link.rel = "icon";
|
|
|
- document.head.appendChild(link);
|
|
|
- const alerts: AlertMessage[] = [
|
|
|
- { atype: "success", message: "This is a system alert", system: true, duration: 3000 },
|
|
|
- ];
|
|
|
- render(
|
|
|
- <SnackbarProvider>
|
|
|
- <Alert alerts={alerts} />
|
|
|
- </SnackbarProvider>,
|
|
|
- );
|
|
|
- const linkElement = document.querySelector("link[rel='icon']");
|
|
|
- expect(linkElement?.getAttribute("href") || "/favicon.png").toBe("/favicon.png");
|
|
|
- document.head.removeChild(link);
|
|
|
+ it("does not render if render prop is false", () => {
|
|
|
+ const { queryByRole } = render(<TaipyAlert message="Hidden Alert" render={false} />);
|
|
|
+ const alert = queryByRole("alert");
|
|
|
+ expect(alert).toBeNull();
|
|
|
});
|
|
|
|
|
|
- it("validates href when rel attribute is 'shortcut icon' and href is provided", () => {
|
|
|
- const link = document.createElement("link");
|
|
|
- link.rel = "shortcut icon";
|
|
|
- link.href = "/test-shortcut-icon.png";
|
|
|
- document.head.appendChild(link);
|
|
|
- const alerts: AlertMessage[] = [
|
|
|
- { atype: "success", message: "This is a system alert", system: true, duration: 3000 },
|
|
|
- ];
|
|
|
- render(
|
|
|
- <SnackbarProvider>
|
|
|
- <Alert alerts={alerts} />
|
|
|
- </SnackbarProvider>,
|
|
|
- );
|
|
|
- const linkElement = document.querySelector("link[rel='shortcut icon']");
|
|
|
- expect(linkElement?.getAttribute("href")).toBe("/test-shortcut-icon.png");
|
|
|
- document.head.removeChild(link);
|
|
|
+ it("handles dynamic class names", () => {
|
|
|
+ const { getByRole } = render(<TaipyAlert message="Dynamic Alert" className="custom-class" />);
|
|
|
+ const alert = getByRole("alert");
|
|
|
+ expect(alert).toHaveClass("custom-class");
|
|
|
});
|
|
|
});
|