typescript 如何测试更改状态

dffbzjpn  于 2023-01-21  发布在  TypeScript
关注(0)|答案(1)|浏览(111)

我在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
    });
});

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

4ioopgfo

4ioopgfo1#

@Ibsn是对的,RTL希望你通过查看DOM中的元素来Assert状态已经改变,如果你用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
希望这个有用。

相关问题