reactjs 测试状态变量从React测试库中的父级向下传递的组件

ubof19bj  于 2022-12-22  发布在  React
关注(0)|答案(1)|浏览(117)

我对测试非常陌生,但我知道在大型应用程序中它是必要的。我正在使用React测试库向我的第一个组件添加单元测试。它是一个注解组件,用户可以在其中键入注解,点击按钮,它将在div中显示注解及其上方的任何其他注解。如果不存在注解,那个div没有显示。comments组件正在接受从父组件传下来的状态属性。
下面是我在测试中创建组件的方法(我甚至不确定测试中是否允许/推荐使用状态):

function EmptyComments() {
    const [comment, setComment] = useState('');
    const [comments, setComments] = useState([]);
    const saveComment = () => {
        const today = new Date();
        const newComment = {
            id: comment.length+1,
            comment: comment,
            date: today.toISOString(),
        };
        setComments(prevState => {
            return [...prevState, newComment]
        })
    }
    return <Comments
        comments={comments}
        commentMsg={''}
        setCommentMsg={mockedEmptyFn}
        comment={comment}
        setComment={setComment}
        saveComment={saveComment}
        deleteCommentAPI={mockedEmptyFn}
    />
}

那我失败的测试

test('Should display a newly typed comment', async() => {
        render(<EmptyComments />);
        const textArea = screen.getByPlaceholderText('Type new comment...');
        await userEvent.type(textArea, 'A new test comment!');
        const saveButton = screen.queryByRole('button', {
            name: /Save Comment/i
        });
        await userEvent.click(saveButton);
        await waitFor(() => {
            const commentsContainer = screen.findByTestId('comments');
            expect(commentsContainer).toBeInTheDocument();
        });
    });

最后,我想展示我的comments组件的一个片段,以说明如何显示或隐藏comments容器:

{comments && comments.length > 1 ? (
    <div className={'comments'} data-testid={'comments'}>

所以我不知道我是否需要更新屏幕视图,或者我做错了什么。

4uqofj5v

4uqofj5v1#

你不应该在你的测试中需要状态。另外,这样做只会增加更多的代码,这些代码可能不可靠,也不能真正被测试。我的建议是做两个测试。
1.检查在输入数据并点击保存按钮时,saveComment函数是否被输入的值调用。
1.检查当您发送注解时,注解是否显示。
这样做可以保证调用所有内容并按预期显示。
如果您想用现在的方法测试它,您必须为Parent组件编写测试,以便自动设置所有状态。
像这样的东西应该为您工作(我没有测试这个,所以一些finagling可能仍然要做)

const mockBaseProps = {
  comments: [],
  commentMsg: '',
  setCommentMsg: jest.fn(),
  comment: '',
  setComment: jest.fn(),
  saveComment: jest.fn(),
  deleteCommentAPI: jest.fn(),
};
const mockComment = 'A new test comment!';

// Creating a new component just so that the `mockBaseProps` get spread in every time and you don't have to always redefine them.
const Component = (props) => <Comments {...mockBaseProps} {...props} />;

test('can add a comment', async () => {
  render(<Component />);

  const textArea = screen.getByPlaceholderText('Type new comment...');
  await userEvent.type(textArea, mockComment);

  const saveButton = screen.queryByRole('button', { name: /Save Comment/i });
  await userEvent.click(saveButton);

  expect(mockBaseProps.saveComment).toHaveBeenCalledTimes(1);
  expect(mockBaseProps.saveComment).toHaveBeenCalledWith(mockComment);
});

test('comment displays', () => {
  render(
    <Component
      comments={[
        id: mockComment.length + 1,
        comment: mockComment,
        date: new Date().toISOString(),
      ]}
    />
  );

  await waitFor(() => expect(screen.getByTestId('comments')).toBeInTheDocument());

  /**
   * Note that `*ByTestId` is not generally recommended. It would be better to check that the actual comment text displays.
   * https://testing-library.com/docs/queries/about#priority
   *
   * Something like:
   * 
   * await waitFor(() => expect(screen.getByText(mockComment)).toBeInTheDocument());
   */
});

相关问题