import React, { FunctionComponent, HTMLAttributes, ReactNode } from "react";
import {
act,
cleanup,
fireEvent,
render,
testHook,
} from "react-testing-library";
import useSearchEventHandler, {
SearchEffectOptions,
} from "../useSearchEventHandler";
jest.useFakeTimers();
const progress = () =>
act(() => {
jest.runAllTimers();
});
describe("useSearchEventHandler", () => {
const onKeyboardFocus = jest.fn();
afterEach(() => {
cleanup();
progress();
onKeyboardFocus.mockClear();
});
it("should return the correct object", () => {
let value;
testHook(
() => (value = useSearchEventHandler({ onKeyboardFocus, handlers: {} }))
);
expect(value).toEqual({
handlers: expect.objectContaining({
onKeyDown: expect.any(Function),
}),
});
});
describe("event handler", () => {
type TestType = FunctionComponent<
{
items?: ReactNode[];
onKeyDown?: HTMLAttributes["onKeyDown"];
} & Pick<
SearchEffectOptions,
"searchResetTime" | "getValues" | "findMatchIndex"
>
>;
const Test: TestType = ({
items = ["Item 1", "Item 2", "Item 3", "Item 4"],
onKeyDown: propOnKeyDown,
...others
}) => {
const { handlers } = useSearchEventHandler({
...others,
onKeyboardFocus,
handlers: { onKeyDown: propOnKeyDown },
});
return (
);
};
it("should call the prop onKeyDown", () => {
const onKeyDown = jest.fn();
const { getByRole } = render();
fireEvent.keyDown(getByRole("menu"));
jest.runAllTimers();
expect(onKeyDown).toBeCalled();
});
it("should not call the onKeyboardFocus when the key has a length greater than 1", () => {
const { getByRole } = render();
const menu = getByRole("menu");
fireEvent.keyDown(menu, { key: "Unidentified" });
progress();
fireEvent.keyDown(menu, { key: "Tab" });
progress();
fireEvent.keyDown(menu, { key: "Home" });
progress();
fireEvent.keyDown(menu, { key: "Shift" });
progress();
fireEvent.keyDown(menu, { key: "Alt" });
progress();
fireEvent.keyDown(menu, { key: "Option" });
progress();
fireEvent.keyDown(menu, { key: "Enter" });
progress();
expect(onKeyboardFocus).not.toBeCalled();
});
it("should not call the onKeyboardFocus if the seach string can not be found in the items", () => {
const { getByRole } = render();
const menu = getByRole("menu");
fireEvent.keyDown(menu, { key: "A" });
progress();
fireEvent.keyDown(menu, { key: "a" });
progress();
fireEvent.keyDown(menu, { key: "t" });
progress();
expect(onKeyboardFocus).not.toBeCalled();
});
it("should call the onKeyboardFocus with the correct values when there is a match", () => {
const { container } = render();
const items = container.querySelectorAll("[role='menuitem']");
fireEvent.keyDown(items[0], { key: "I" });
expect(onKeyboardFocus).toBeCalledWith(
expect.objectContaining({
element: items[1],
elementIndex: 1,
// using items causes a memeory leak for some reason
focusableElements: expect.any(Array),
}),
expect.any(Object)
);
fireEvent.keyDown(items[1], { key: "t" });
expect(onKeyboardFocus).toBeCalledWith(
expect.objectContaining({
element: items[2],
elementIndex: 2,
focusableElements: expect.any(Array),
}),
expect.any(Object)
);
});
});
});