遗漏了React Admin覆盖范围的React Jest测试

pkbketx9  于 2022-12-20  发布在  Jest
关注(0)|答案(1)|浏览(224)

我试图测试React Admin,但是当我运行test:coverage时,我收到了未覆盖的行:
| 文件|%样本|分支机构%| %功能|%线|未覆盖行号|
| - ------| - ------| - ------| - ------| - ------| - ------|
| TestCreate.tsx|五十五点五十五分|一百|四十|五十五点五十五分|十九至二十、三十二至三十八|
它似乎指向SimpleToolbar方法的窗口。scrollTo和突变选项onSuccess ...
我如何测试这两个?
以下来源:
TestCreate.tsx

import * as React from 'react';
import {
  Create,
  SimpleForm,
  SaveButton,
  useNotify,
  TextInput,
  CreateProps,
  Toolbar,
  required,
} from 'react-admin';
import { Button } from '@mui/material';
import { useFormContext } from 'react-hook-form';

function SimpleToolbar() {
  const notify = useNotify();
  const { reset } = useFormContext();
  const onSuccess = (data: { email: string }): void => {
    window.scrollTo(0, 0);
    notify(`${data.email} submit successfully.`, {
      type: 'success',
      messageArgs: 'form has been submitted',
    });
  };

  return (
    <Toolbar>
      <SaveButton
        type="button"
        label="Submit"
        mutationOptions={{
          onSuccess: (data) => { onSuccess(data); },
        }}
      />
      <Button
        type="reset"
        onClick={() => {
          reset();
        }}
      >
        CLEAR
      </Button>
    </Toolbar>
  );
}

function TestCreate(props: CreateProps) {
  return (
    <Create {...props}>
      <SimpleForm toolbar={<SimpleToolbar />}>
        <TextInput source="name" label="Name" validate={required()} />
        <TextInput source="email" label="Email" validate={required()} />
      </SimpleForm>
    </Create>
  );
}

export default TestCreate;

TestCreate.spec.tsx:

import { render, screen } from '@testing-library/react';
import { AdminContext, ResourceContextProvider, testDataProvider } from 'react-admin';

import TestCreate from './TestCreate';

describe('<TestCreate />', () => {
  const dataProvider = testDataProvider({
    create: jest.fn().mockResolvedValueOnce({ data: { name: 'Jason', email: 'jason@gmail.com' } }),
  });
  it('should render components', async () => {
    render(
      <AdminContext dataProvider={dataProvider as any}>
        <ResourceContextProvider value="test">
          <TestCreate />
        </ResourceContextProvider>
      </AdminContext>,
    );

    const nameInput = await screen.findByText('Name');
    expect(nameInput).toBeInTheDocument();
    const emailInput = await screen.findByText('Email');
    expect(emailInput).toBeInTheDocument();
  });
});
n53p2ov0

n53p2ov01#

在您的组件上,当您单击<SaveButton>并且请求成功时,onSuccess将被调用,这意味着要对此进行测试,您需要在按钮上触发一个单击事件,并检查您期望发生的事情是否发生了。
假设您想测试所有内容,那么您需要做两件事:scrollTonotify。要测试它们,您需要使用mockuseNotify()并监视window.scrollTo。对于后者,我使用了this question上的答案。对于useNotify,您可以使用mockReturnValue()并编写如下模拟:

jest.mock("react-admin", () => ({
  ...jest.requireActual("react-admin"),
  useNotify: jest.fn();
});

您还必须确保dataProvider返回成功响应。
下面是该测试可能的样子:

it("scrolls to the correct position and notifies on success", async () => {
  const mockNotify = jest.fn();
  const scrollToSpy = jest.fn();
  useNotify.mockReturnValue(mockNotify);
  global.scrollTo = scrollToSpy;

  render(
    <AdminContext dataProvider={dataProvider as any}>
      <ResourceContextProvider value="test">
        <TestCreate />
      </ResourceContextProvider>
    </AdminContext>,
  );
  const saveButton = screen.getByRole("button", { name: "Submit" });
  fireEvent.click(saveButton);

  await waitFor(() => {
    expect(mockNotify).toHaveBeenCalledWith(...); // If you want to test the params
    expect(scrollToSpy).toHaveBeenCalledWith(0, 0);
  });
});

你还有两件事要处理:

  • 模拟useNotify也会影响其他测试,因为代码期望useNotify()返回一个函数,如果你没有在每个测试中正确模拟它,你会得到一个错误。你是否决定在你的文件上使用constbeforeEach(),或者其他东西来解决这个问题取决于你。
  • 同样的道理也适用于您对dataProvidercreate的模拟。您只模拟它一次,所以如果您需要多个测试的响应,您可能会遇到问题。

顺便说一句,我添加了一个waitFor(),因为我记得有时RA和这类调用需要它,但我认为这取决于您的代码,所以可能没有必要。

相关问题