
[英]How to test a method which is resolving a promise and then changing state in React?
[英]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.