|
@@ -12,19 +12,20 @@
|
|
*/
|
|
*/
|
|
|
|
|
|
import React from "react";
|
|
import React from "react";
|
|
-import { render } from "@testing-library/react";
|
|
|
|
|
|
+import { render, screen, waitFor } from "@testing-library/react";
|
|
import "@testing-library/jest-dom";
|
|
import "@testing-library/jest-dom";
|
|
import { SnackbarProvider } from "notistack";
|
|
import { SnackbarProvider } from "notistack";
|
|
|
|
|
|
import Alert from "./Alert";
|
|
import Alert from "./Alert";
|
|
import { AlertMessage } from "../../context/taipyReducers";
|
|
import { AlertMessage } from "../../context/taipyReducers";
|
|
|
|
+import userEvent from "@testing-library/user-event";
|
|
|
|
|
|
const defaultMessage = "message";
|
|
const defaultMessage = "message";
|
|
const defaultAlerts: AlertMessage[] = [{ atype: "success", message: defaultMessage, system: true, duration: 3000 }];
|
|
const defaultAlerts: AlertMessage[] = [{ atype: "success", message: defaultMessage, system: true, duration: 3000 }];
|
|
-const getAlertsWithType = (aType: string) => [{...defaultAlerts[0], atype: aType}];
|
|
|
|
|
|
+const getAlertsWithType = (aType: string) => [{ ...defaultAlerts[0], atype: aType }];
|
|
|
|
|
|
class myNotification {
|
|
class myNotification {
|
|
- static requestPermission = jest.fn();
|
|
|
|
|
|
+ static requestPermission = jest.fn(() => Promise.resolve("granted"));
|
|
static permission = "granted";
|
|
static permission = "granted";
|
|
}
|
|
}
|
|
|
|
|
|
@@ -32,29 +33,170 @@ describe("Alert Component", () => {
|
|
beforeAll(() => {
|
|
beforeAll(() => {
|
|
globalThis.Notification = myNotification as unknown as jest.Mocked<typeof Notification>;
|
|
globalThis.Notification = myNotification as unknown as jest.Mocked<typeof Notification>;
|
|
});
|
|
});
|
|
|
|
+ beforeEach(() => {
|
|
|
|
+ jest.clearAllMocks();
|
|
|
|
+ });
|
|
it("renders", async () => {
|
|
it("renders", async () => {
|
|
- const { getByText } = render(<SnackbarProvider><Alert alerts={defaultAlerts} /></SnackbarProvider>);
|
|
|
|
|
|
+ const { getByText } = render(
|
|
|
|
+ <SnackbarProvider>
|
|
|
|
+ <Alert alerts={defaultAlerts} />
|
|
|
|
+ </SnackbarProvider>,
|
|
|
|
+ );
|
|
const elt = getByText(defaultMessage);
|
|
const elt = getByText(defaultMessage);
|
|
expect(elt.tagName).toBe("DIV");
|
|
expect(elt.tagName).toBe("DIV");
|
|
});
|
|
});
|
|
it("displays a success alert", async () => {
|
|
it("displays a success alert", async () => {
|
|
- const { getByText } = render(<SnackbarProvider><Alert alerts={defaultAlerts} /></SnackbarProvider>);
|
|
|
|
|
|
+ const { getByText } = render(
|
|
|
|
+ <SnackbarProvider>
|
|
|
|
+ <Alert alerts={defaultAlerts} />
|
|
|
|
+ </SnackbarProvider>,
|
|
|
|
+ );
|
|
const elt = getByText(defaultMessage);
|
|
const elt = getByText(defaultMessage);
|
|
- expect(elt.closest(".notistack-MuiContent-success")).toBeInTheDocument()
|
|
|
|
|
|
+ expect(elt.closest(".notistack-MuiContent-success")).toBeInTheDocument();
|
|
});
|
|
});
|
|
it("displays an error alert", async () => {
|
|
it("displays an error alert", async () => {
|
|
- const { getByText } = render(<SnackbarProvider><Alert alerts={getAlertsWithType("error")} /></SnackbarProvider>);
|
|
|
|
|
|
+ const { getByText } = render(
|
|
|
|
+ <SnackbarProvider>
|
|
|
|
+ <Alert alerts={getAlertsWithType("error")} />
|
|
|
|
+ </SnackbarProvider>,
|
|
|
|
+ );
|
|
const elt = getByText(defaultMessage);
|
|
const elt = getByText(defaultMessage);
|
|
- expect(elt.closest(".notistack-MuiContent-error")).toBeInTheDocument()
|
|
|
|
|
|
+ expect(elt.closest(".notistack-MuiContent-error")).toBeInTheDocument();
|
|
});
|
|
});
|
|
it("displays a warning alert", async () => {
|
|
it("displays a warning alert", async () => {
|
|
- const { getByText } = render(<SnackbarProvider><Alert alerts={getAlertsWithType("warning")} /></SnackbarProvider>);
|
|
|
|
|
|
+ const { getByText } = render(
|
|
|
|
+ <SnackbarProvider>
|
|
|
|
+ <Alert alerts={getAlertsWithType("warning")} />
|
|
|
|
+ </SnackbarProvider>,
|
|
|
|
+ );
|
|
const elt = getByText(defaultMessage);
|
|
const elt = getByText(defaultMessage);
|
|
- expect(elt.closest(".notistack-MuiContent-warning")).toBeInTheDocument()
|
|
|
|
|
|
+ expect(elt.closest(".notistack-MuiContent-warning")).toBeInTheDocument();
|
|
});
|
|
});
|
|
it("displays an info alert", async () => {
|
|
it("displays an info alert", async () => {
|
|
- const { getByText } = render(<SnackbarProvider><Alert alerts={getAlertsWithType("info")} /></SnackbarProvider>);
|
|
|
|
|
|
+ const { getByText } = render(
|
|
|
|
+ <SnackbarProvider>
|
|
|
|
+ <Alert alerts={getAlertsWithType("info")} />
|
|
|
|
+ </SnackbarProvider>,
|
|
|
|
+ );
|
|
const elt = getByText(defaultMessage);
|
|
const elt = getByText(defaultMessage);
|
|
- expect(elt.closest(".notistack-MuiContent-info")).toBeInTheDocument()
|
|
|
|
|
|
+ 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();
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ it("does nothing when alert is undefined", async () => {
|
|
|
|
+ render(
|
|
|
|
+ <SnackbarProvider>
|
|
|
|
+ <Alert alerts={[]} />
|
|
|
|
+ </SnackbarProvider>,
|
|
|
|
+ );
|
|
|
|
+ expect(Notification.requestPermission).not.toHaveBeenCalled();
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ 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("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("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);
|
|
});
|
|
});
|
|
});
|
|
});
|