import * as React from "react"; import { act, fireEvent, render, waitFor, waitForElementToBeRemoved } from "@testing-library/react"; import { Toaster, Toast } from "../"; import { DEFAULT_DELAY_TIME } from "../components/Toaster"; import userEvent from "@testing-library/user-event"; describe("Toaster", () => { afterEach(() => { jest.useRealTimers(); }); it("displays toast children", () => { const title = "I Am Toast"; const { getByText } = render( ); expect(getByText(title)).toBeInTheDocument(); }); it("dismisses toasts when child is clicked", async () => { const user = userEvent.setup(); const title = "I Am Toast"; const testToast = []; const { getByRole, queryByText } = render({testToast}); await user.click(getByRole("button")); await waitFor(() => { expect(queryByText(title)).not.toBeInTheDocument(); }); }); it("calls onDismiss callback when toast is dismissed", async () => { const user = userEvent.setup(); const dismissCallback = jest.fn(); const testToast = [ ]; const { getByRole } = render({testToast}); await user.click(getByRole("button")); expect(dismissCallback).toHaveBeenCalledTimes(1); }); it("dismisses autodismiss toasts after a default time", async () => { jest.useFakeTimers(); const title = "I Am Toast"; const { getByText, queryByText } = render( ); expect(getByText(title)).toBeDefined(); await waitFor(() => { expect(queryByText(title)).toBeInTheDocument(); }); void act(() => { jest.advanceTimersByTime(DEFAULT_DELAY_TIME); }); await waitFor(() => { expect(queryByText(title)).not.toBeInTheDocument(); }); }); it("dismisses autodismiss toasts after specified time", async () => { jest.useFakeTimers(); const title = "I Am Toast"; const { getByText, queryByText } = render( ); expect(getByText(title)).toBeDefined(); await waitFor(() => { expect(queryByText(title)).toBeInTheDocument(); }); void act(() => { jest.advanceTimersByTime(8000); }); await waitFor(() => { expect(queryByText(title)).not.toBeInTheDocument(); }); }); it("pauses autodismiss if user hovers on item", async () => { jest.useFakeTimers(); const title = "I Am Toast"; const { getByTestId, queryByText } = render( ); const toasterList = getByTestId("toaster-list"); // for some reason using RTL user event and jest timers didn't work fireEvent.mouseEnter(toasterList); void act(() => { jest.advanceTimersByTime(DEFAULT_DELAY_TIME); }); // is never removed because timeout was cleared await expect( waitForElementToBeRemoved(() => queryByText(title)) ).rejects.toThrow(); fireEvent.mouseLeave(toasterList); void act(() => { jest.advanceTimersByTime(DEFAULT_DELAY_TIME); }); await waitFor(() => { expect(queryByText(title)).not.toBeInTheDocument(); }); }); it("calls onDismiss callback for autodismissed toasts", () => { jest.useFakeTimers(); const dismissCallback = jest.fn(); const testToast = ( ); render({testToast}); expect(dismissCallback).not.toHaveBeenCalled(); void act(() => { jest.advanceTimersByTime(DEFAULT_DELAY_TIME); }); expect(dismissCallback).toHaveBeenCalledTimes(1); }); it("adds new `toast` with new toast received via props", () => { const testToastId = "testToastId"; const { rerender, getByText, queryByText } = render( ); expect(getByText("I Am Toast")).toBeInTheDocument(); const newProps = { children: [ , ] }; rerender({newProps.children}); expect(queryByText("I Am Toast")).not.toBeInTheDocument(); expect(getByText("I Am A Different Toast")).toBeInTheDocument(); expect(getByText("I Am A Slightly Different Toast")).toBeInTheDocument(); }); });