繁体   English   中英

如何测试更改 state

[英]How to test changing state

我在 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的 state 是否已更新。

下一个是(仅当expanded state 为true时),检查非活动元素上的点击事件并检查该点击事件是否将 expanded state 更新回 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
    });
});

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

@Ibsn 是对的。 RTL 希望您通过查看 DOM 中的元素来断言 state 已更改。 如果你用 CSS 隐藏你的元素,你不能轻易确认组件是否真的可见,但你可以通过 class 名称查询 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);
});

来源

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

<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>

这是一个工作代码框示例

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

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

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

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

此外,根据我的阅读,现在推荐使用userEvent而不是fireEvent

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM