Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: improved toast tests #41

Merged
merged 33 commits into from
Sep 15, 2020
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
98a7ad7
test: jest testing setup
anuraghazra Sep 7, 2020
77b3e5b
test: fixed jest typescript definitions
anuraghazra Sep 7, 2020
6c6851d
fix: test script
anuraghazra Sep 8, 2020
48522b3
chore(deps): move deps to dev
anuraghazra Sep 8, 2020
75be5a5
chore: fix conflicts
anuraghazra Sep 8, 2020
a2ccec2
Merge branch 'master' into tests
anuraghazra Sep 8, 2020
faf10fd
test: added tests for accordion
anuraghazra Sep 8, 2020
aa0fe98
Merge branch 'master' into tests
anuraghazra Sep 9, 2020
c2e3582
test: added husky precommit test
anuraghazra Sep 9, 2020
56e5b8c
test: axe container test
anuraghazra Sep 9, 2020
c6c1fa1
chore(infra): added github action test
anuraghazra Sep 9, 2020
7452121
test: added tests for number input
anuraghazra Sep 9, 2020
4a3af5f
fix: a11y aria-valuetext issue with NumberInput
anuraghazra Sep 9, 2020
6b9d8ef
test: added tests for Slider
anuraghazra Sep 9, 2020
51a27fa
Merge branch 'master' into tests
anuraghazra Sep 9, 2020
26a5d63
Merge branch 'master' into tests
anuraghazra Sep 9, 2020
9e2da6d
Merge branch 'master' into tests
anuraghazra Sep 10, 2020
7962d34
test: added tests for progress
anuraghazra Sep 10, 2020
4d62f99
test: added tests for link
anuraghazra Sep 10, 2020
6b1ee43
Merge branch 'master' into tests
anuraghazra Sep 10, 2020
d402c58
Merge branch 'master' into tests
anuraghazra Sep 11, 2020
3e6e092
test: added tests for breadcrumb
anuraghazra Sep 11, 2020
01c5d9e
test: added tests for pagination
anuraghazra Sep 11, 2020
8ee7ab4
Merge branch 'master' into tests
anuraghazra Sep 11, 2020
9d75afc
test: added tests for toast
anuraghazra Sep 11, 2020
b4c4f6a
Merge branch 'master' into tests
anuraghazra Sep 11, 2020
54b7aff
chore(deps): remove unused raf
anuraghazra Sep 11, 2020
7aea878
Merge branch 'master' into tests
anuraghazra Sep 14, 2020
9fa89e7
fix: broken build
anuraghazra Sep 14, 2020
b491b97
Merge branch 'tests' of https://github.com/timelessco/renderless-comp…
anuraghazra Sep 14, 2020
cc7a5eb
test: improved & fixed toast tests
anuraghazra Sep 14, 2020
3c26e61
Merge branch 'master' into toast-test-fix
anuraghazra Sep 15, 2020
3d7e1f7
test: fixed warning on toast tests
anuraghazra Sep 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/toast/ToastProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { createContext } from "@chakra-ui/utils";

import { ToastStateReturn } from "./ToastState";
import { ToastController } from "./ToastController";
import useToastState, { IToast } from "./ToastState";
import { useToastState, IToast } from "./ToastState";

const DEFAULT_TIMEOUT = 5000;
const PLACEMENTS = {
Expand Down
4 changes: 1 addition & 3 deletions src/toast/ToastState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface ToastStateProps {
animationTimeout?: number;
}

const useToastState = ({ animationTimeout = 0 }: ToastStateProps) => {
export const useToastState = ({ animationTimeout = 0 }: ToastStateProps) => {
const [toasts, setToasts] = React.useState<ToastList>({});

// toggle can be used to just hide/show the toast instead of removing it.
Expand Down Expand Up @@ -140,5 +140,3 @@ const useToastState = ({ animationTimeout = 0 }: ToastStateProps) => {
};

export type ToastStateReturn = ReturnType<typeof useToastState>;

export default useToastState;
178 changes: 178 additions & 0 deletions src/toast/__tests__/Toast.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import * as React from "react";
import { axe } from "jest-axe";
import { render, click, act } from "reakit-test-utils";

import { useToast, ToastProvider } from "..";

beforeEach(() => {
jest.useFakeTimers();
jest
.spyOn(window, "requestAnimationFrame")
.mockImplementation((cb: any) => cb());
jest.spyOn(window, "setTimeout").mockImplementation((cb: any) => cb());
});

afterEach(() => {
(window.requestAnimationFrame as any).mockRestore();
(window.setTimeout as any).mockRestore();
});

const Demo = () => {
const { show } = useToast();

return (
<div>
<button
onClick={() => {
show({
type: "error",
content: "This is error",
});
}}
>
Error
</button>
<button
onClick={() => {
show({ type: "success", content: "This is success" });
}}
>
Success
</button>
<button
onClick={() => {
show({ type: "warning", content: "This is warning" });
}}
>
Warning
</button>
<button
onClick={() => {
show({
content: () => (
<p style={{ fontFamily: "Impact", color: "black" }}>
This is Custom
</p>
),
});
}}
>
Custom
</button>
</div>
);
};

const ToastComp: React.FC = () => {
return (
<ToastProvider
placement="bottom-center"
toastTypes={{
error: ({ remove, content, id }) => {
return (
<div
data-testid="error"
className="toast"
style={{ backgroundColor: "#f02c2d" }}
>
{content}{" "}
<button data-testid="error-close" onClick={() => remove(id)}>
x
</button>
</div>
);
},
success: ({ remove, content, id }) => {
return (
<div className="toast" style={{ backgroundColor: "#01c24e" }}>
{content} <button onClick={() => remove(id)}>x</button>
</div>
);
},
warning: ({ remove, content, id }) => {
return (
<div className="toast" style={{ backgroundColor: "#ef5013" }}>
{content} <button onClick={() => remove(id)}>x</button>
</div>
);
},
}}
>
<Demo />
</ToastProvider>
);
};

describe("Toast", () => {
it("should render correctly", () => {
const { baseElement } = render(<ToastComp />, {
container: document.body,
});

expect(baseElement).toMatchInlineSnapshot(`
<body>
<div>
<button>
Error
</button>
<button>
Success
</button>
<button>
Warning
</button>
<button>
Custom
</button>
</div>
</body>
`);
});

it("toast should popup to the screen after click", () => {
const { getByText: text, getByTestId: id } = render(<ToastComp />, {
container: document.body,
});

expect(text("Error")).toBeInTheDocument();

act(() => {
click(text("Error"));
});

expect(id("error")).toHaveTextContent("This is error");
});

it("should be removed after clicking close button", () => {
const {
getByText: text,
queryByTestId: queryId,
getByTestId: getId,
} = render(<ToastComp />, {
container: document.body,
});

expect(text("Error")).toBeInTheDocument();

// add first
act(() => {
click(text("Error"));
});

expect(getId("error")).toHaveTextContent("This is error");

// let remove now
act(() => {
click(getId("error-close"));
});

expect(queryId("error")).not.toBeInTheDocument();
});

test("Toast renders with no a11y violations", async () => {
const { container } = render(<ToastComp />);
const results = await axe(container);

expect(results).toHaveNoViolations();
});
});
174 changes: 174 additions & 0 deletions src/toast/__tests__/ToastState.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import { wait } from "reakit-test-utils";
import { renderHook, act } from "@testing-library/react-hooks";

import { useToastState } from "..";

beforeEach(() => {
jest.useFakeTimers();
jest
.spyOn(window, "requestAnimationFrame")
.mockImplementation((cb: any) => cb());
});

afterEach(() => {
(window.requestAnimationFrame as any).mockRestore();
});

describe("ToastState", () => {
it("should render correctly", () => {
const state = renderHook(() => useToastState({})).result;

expect(state.current).toMatchInlineSnapshot(`
Object {
"getToastToRender": [Function],
"hide": [Function],
"remove": [Function],
"setToasts": [Function],
"show": [Function],
"toasts": Object {},
"toggle": [Function],
}
`);
});

it("should add a new toast", () => {
const { result } = renderHook(() => useToastState({}));

expect(result.current.toasts).toStrictEqual({});

act(() => {
result.current.show({ type: "primary", content: "Hello world" });
});
expect(Object.values(result.current.toasts)).toMatchObject([
{
autoDismiss: undefined,
content: "Hello world",
isVisible: true,
placement: undefined,
timeout: undefined,
type: "primary",
},
]);
});

it("should toggle toast", () => {
const { result } = renderHook(() => useToastState({}));

expect(result.current.toasts).toStrictEqual({});

act(() => {
result.current.show({ type: "primary", content: "Hello world" });
});

const id = Object.values(result.current.toasts)[0].id;

act(() => {
result.current.toggle({ id, isVisible: false });
});
expect(result.current.toasts[id]).toMatchObject({ isVisible: false });
});

it("should remove toast", () => {
const { result } = renderHook(() => useToastState({}));

expect(result.current.toasts).toStrictEqual({});

act(() => {
result.current.show({ type: "primary", content: "Hello world" });
});
expect(Object.values(result.current.toasts)).toHaveLength(1);
const id = Object.values(result.current.toasts)[0].id;

act(() => {
result.current.remove(id);
});
expect(result.current.toasts).toStrictEqual({});
});

it("should hide toast", () => {
const { result } = renderHook(() => useToastState({ animationTimeout: 5 }));
let id = "";

expect(result.current.toasts).toStrictEqual({});

act(() => {
result.current.show({ type: "primary", content: "Hello world" });
});
expect(Object.values(result.current.toasts)).toHaveLength(1);
id = Object.values(result.current.toasts)[0].id;

act(() => {
result.current.hide(id);
});
expect(Object.values(result.current.toasts)).toMatchObject([
{
autoDismiss: undefined,
content: "Hello world",
isVisible: false,
placement: undefined,
timeout: undefined,
type: "primary",
},
]);

// Wait for animation timeout and after that toast should be removed
wait(
() => {
expect(result.current.toasts).toStrictEqual({});
},
{ timeout: 5 },
);
});

it("should test getToastToRender", () => {
const { result } = renderHook(() => useToastState({}));

expect(result.current.toasts).toStrictEqual({});

act(() => {
result.current.show({
type: "primary",
placement: "top-center",
content: "Hello world 1",
});
result.current.show({
type: "primary",
placement: "bottom-center",
content: "Hello world 2",
});
result.current.show({
type: "primary",
placement: "bottom-left",
content: "Hello world 3",
});
result.current.show({
type: "primary",
placement: "bottom-left",
content: "Hello world 4",
});
result.current.show({
type: "primary",
placement: "top-right",
content: "Hello world 5",
});
});

const allPositions: any[] = [];
result.current.getToastToRender("bottom-center", (pos, toastList) => {
allPositions.push(toastList);
});
expect(allPositions[0]).toHaveLength(1);
expect(allPositions[1]).toHaveLength(1);
expect(allPositions[2]).toHaveLength(2);
expect(allPositions[3]).toHaveLength(1);

expect(allPositions[2][0]).toMatchObject({
content: "Hello world 3",
placement: "bottom-left",
});
expect(allPositions[2][1]).toMatchObject({
content: "Hello world 4",
placement: "bottom-left",
});
});
});
Loading