@secondcloset/frontend-test-utils
TypeScript icon, indicating that this package has built-in type declarations

1.0.2 • Public • Published

@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 of RecoilRoot
  • result
    • set: SetterOrUpdater<T> - this functions is used to set Recoil state value
    • reset: Resetter - this function is used to reset Recoil state value
    • value: 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 component
  • render: (props: PropsWithChildren<T>) => ReactNode - custom render function

Returns

  • props: { current: PropsWithChildren<T> } - component props (including children)

Notes

  • It is possible to use jest.Mock instead of jest.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" });
});

Package Sidebar

Install

npm i @secondcloset/frontend-test-utils

Weekly Downloads

10

Version

1.0.2

License

MIT

Unpacked Size

11.6 kB

Total Files

15

Last publish

Collaborators

  • paollenado
  • rafslzr-gb
  • raymondgabriel
  • arnaldo.tayao
  • redlpd-gb
  • michaelgoboltnpm
  • selinasha
  • snoopy55619819-bolt
  • virgilligobolt
  • jorge_h_ramos_dev
  • jaybihbolt
  • michaelellisbolt
  • kyosan.ku
  • keleung
  • fadil.mamedov
  • dkpbolt
  • scdevelopers
  • chankakyan
  • tralfamadorian
  • sephlao
  • alexcheng068
  • krisha-sc
  • fbadin-sc
  • annielyz
  • hsmysk
  • john2021