【问题标题】:How to test changing state如何测试改变状态
【发布时间】:2023-01-21 13:03:12
【问题描述】:

我在 TypeScript 中有如下组件:

import React, {useState} from 'react';
import {App} from "../../../../interfaces/interfaces";
import {map, find, filter} from "lodash";
import NavigationItem from "./NavigationItem";
import {useLocation, useNavigate} from 'react-router-dom';

interface NavigationProps {
    applications: App[],
    companyName: string
}

const Navigation: React.FC<NavigationProps> = ({applications, companyName}: NavigationProps) => {
    const [expanded, setExpanded] = useState<boolean>(false)
    const location = useLocation();
    const navigate = useNavigate();

    const activeApplication = find(applications, application => application.url === location.pathname);
    const inactiveApplications = filter(applications, application => application.url !== location.pathname)

    return (
        <div data-testid="navigation-component" className="flex h-full">
            <div className="z-[2]">
                <NavigationItem application={activeApplication}
                                companyName={companyName}
                                handleClick={() => setExpanded(expanded => !expanded)}
                                selected={expanded}
                />
            </div>

            <div data-testid="inactive-items" className={`flex transform transition ${expanded ? 'translate-x-0' : '-translate-x-full'}`}>
                {map(inactiveApplications, application => {
                    return <NavigationItem key={application.id}
                                           application={application}
                                           companyName={companyName}
                                           handleClick={() => {
                                               setExpanded(false);
                                               navigate(application.url);
                                           }}
                    />
                })}
            </div>
        </div>
    );
};

export default Navigation;

我想为它编写测试。我想测试click event。因此,我应该检查是否已单击活动导航项,以及是否更新了 expanded 状态。

下一个是(仅当 expanded 状态为 true 时),检查非活动元素上的点击事件并检查该点击事件是否将展开状态更新回 false 并导航到另一条路线。

我所拥有的如下:

    import Header from "./Header";
    import Navigation from "./components/Navigation";
    import {MemoryRouter} from "react-router-dom";
    
    import {describe, it} from "@jest/globals";
    import {act, fireEvent, render, screen, waitFor} from "@testing-library/react";
    import userEvent from "@testing-library/user-event";
    
    describe("<Navigation />", () => {
    it("checks navigation clicks events", () => {
        const applications = [
            {id: 1, name: "Home", url: "/", classes: "bg-gray-100 text-blue-800"},
            {id: 3, name: "Sales", url: "/sales", classes: "bg-red-500 text-white"},
            {id: 2, name: "Expert", url: "/expert", classes: "bg-green-400 text-white"}
        ];
        const companyName = 'My company';
        render(<MemoryRouter initialEntries={["/"]}>
            <Navigation applications={applications} companyName={companyName} />
        </MemoryRouter>);

        // Get the selected NavigationItem
        const activeNavigationItem = screen.getByTestId(applications[0].name);

        // Simulate click event
        fireEvent.click(activeNavigationItem);
        // Check if click updated the state, changed expanded to true AND maybe check if other inactive NavigationItems have translate-x-0 class


        // Check if expanded is true, if it's true, then check if clicking one of the other NavigationsItems sets it to false and navigate to proper route
    });
});

我不确定如何获取状态并检查它是否已更改。

【问题讨论】:

标签: reactjs typescript jestjs react-testing-library


【解决方案1】:

@Ibsn 是对的。 RTL 希望您通过查看 DOM 中的元素来断言状态已更改。如果你用 CSS 隐藏你的元素,你不能轻易地确认组件是否真的可见,但你可以通过类名查询 jest-dom。

import {render} from '@testing-library/react';
import App from './App';

test('renders react component', () => {
  const {container} = render(<App />);

  // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
  const boxes = container.getElementsByClassName('box');

  console.log(boxes.length); // ?️ 2

  expect(boxes.length).toBe(2);
});

source

但是,您可能更容易(如果可能的话)使用布尔值显示和隐藏元素。这使得测试更容易。

<div data-testid="inactive-items" className={`flex transform transition`}>
  {map(inactiveApplications, (application) => {
    return expanded && ( // if expanded is false, the component will not render
      <NavigationItem
        key={application.id}
        application={application}
        companyName={companyName}
        selected={expanded}
        handleClick={() => {
          setExpanded(false);
          // navigate(application.url);
        }}
      />
    );
  })}
</div>

这是一个工作codesandbox example

有了这个,你可以将你的测试修改为这样的东西......

const activeNavigationItem = screen.getByTestId(applications[0].name);

expect(activeNavigationItem).not.toBeInTheDocument();
userEvent.click(activeNavigationItem);
expect(activeNavigationItem).toBeInTheDocument();

注意,要使用.toBeInTheDocument,您还必须导入@testing-library/jest-dom

此外,根据我的阅读,userEvent 现在比 fireEvent 更受推荐。

希望这可以帮助。

【讨论】:

    猜你喜欢
    • 2019-06-17
    • 2021-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-25
    相关资源
    最近更新 更多