@secondcloset/frontend-test-utils
v1.0.2
Published
Utilities for testing front-end applications
Downloads
165
Readme
@secondcloset/frontend-test-utils
Utilities for testing front-end applications
Installation
npm install @secondcloset/frontend-test-utils --save-dev
In your test suite:
import { lens, componentLens } from "@secondcloset/frontend-test-utils";
Utilities
lens
Allows to set and read value of Recoil state
const { render, result } = lens(node);
Options
node: RecoilState<T>
- Recoil state
Returns
render: () => JSX.Element
- render this function inside ofRecoilRoot
result
set: SetterOrUpdater<T>
- this functions is used to set Recoil state valuereset: Resetter
- this function is used to reset Recoil state valuevalue: T | undefined
- current value of Recoil state
Example
// usernameState.ts
export const usernameState = atom({
key: "usernameState",
default: "Anonymous",
});
// User.tsx
export const User = () => {
const username = useRecoilValue(usernameState);
return <div>{username}</div>;
};
// User.test.tsx
test("renders username", () => {
const { render: renderUsernameState, result: usernameStateLens } = lens(usernameState);
render(
<RecoilRoot>
{renderUsernameState()}
<User />
</RecoilRoot>
);
let username = screen.queryByText(/anonymous/i);
expect(username).toBeInTheDocument();
act(() => {
usernameStateLens.set("John Doe");
});
username = screen.queryByText(/john doe/i);
expect(username).toBeInTheDocument();
});
// UsernameInput.tsx
export const UsernameInput = () => {
const setUsername = useSetRecoilState(usernameState);
return (
<div>
<input
onChange={(e) => {
setUsername(e.target.value);
}}
/>
</div>
);
};
// UsernameInput.test.tsx
test("updates username", () => {
const { render: renderUsernameState, result: usernameStateLens } = lens(usernameState);
render(
<RecoilRoot>
{renderUsernameState()}
<UsernameInput />
</RecoilRoot>
);
const usernameInput = screen.getByRole("textbox");
userEvent.type(usernameInput, "Michael Scott");
expect(usernameStateLens.value).toBe("Michael Scott");
});
componentLens
Allows to read the prop values of a mocked component that have passed to it during rendering. It is also possible to call functions (usually event handlers) that have been passed as props to that component
const { props } = componentLens(ComponentMock, render?);
Options
componentMock: jest.MockedFunction<React.FC<T>>
- mocked componentrender: (props: PropsWithChildren<T>) => ReactNode
- custom render function
Returns
props: { current: PropsWithChildren<T> }
- component props (includingchildren
)
Notes
- It is possible to use
jest.Mock
instead ofjest.MockedFunction
when mocking component, but you will lose type support for component props
Example
// User.tsx
interface UserProps {
initialUsername: string;
}
export const User: React.FC<UserProps> = ({ initialUsername }) => {
const [username, setUsername] = useState(initialUsername);
return (
<div>
{username}
<UsernameInput
value={username}
onChange={(value) => {
setUsername(value);
}}
/>
</div>
);
};
jest.mock("./UsernameInput");
const UsernameInputMock = UsernameInput as jest.MockedFunction<typeof UsernameInput>;
test("updates username", () => {
const { props: UsernameInputProps } = componentLens(
UsernameInputMock,
({ children }) => <div>{children}</div>
));
render(<User initialUsername="Anonymous" />);
expect(UsernameInputProps.current).toMatchObject({ value: "Anonymous" });
act(() => {
UsernameInputProps.current.onChange("John Doe");
});
expect(UsernameInputProps.current).toMatchObject({ value: "John Doe" });
});