Jest.js 无法在组件内部使用React链接

mwyxok5s  于 2023-04-18  发布在  Jest
关注(0)|答案(2)|浏览(159)

我的React应用程序有一个Item组件,它应该通过单击react-router-domLink组件内的按钮将用户重定向到App组件。我已经遵循了很多教程,这些教程给出了如何在不传递props的组件内实现Link的清晰示例。我的直觉告诉我,我的Item组件属性可能导致了Cannot destructure property 'basename' of 'React__namespace.useContext(...)' as it is null.]错误,因为只有在代码中不存在Link时,才能在Jest上运行测试。

我努力

  • RouteSwitch代码移至index.js
  • 已将components中的脚本移动到src
  • 仔细检查我是否正确地遵循了教程
  • 查看此reactjs - Uncaught TypeError StackOverFlow答案是否与我的问题有关

有人能指出我错过了什么吗?

  • item.js*
import { Link } from "react-router-dom";

const Item = ({info},{addCart}) => {

  return(
    <>
      <Link to="/" ><button>X</button></Link>
      <img src={info.pic} alt={info.title}></img>
      <h1>{info.title}</h1>
      <p>{info.description}</p>
      <button onClick={()=>{addCart(info)}}>Add</button>
    </>
  )
};

export default Item;
  • routeswitch.js *
import React from "react";
import { BrowserRouter,Routes,Route } from "react-router-dom";
import App from "./App"

const RouteSwitch = () =>{
  return(
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<App/>}/>
      </Routes>
    </BrowserRouter>
  );
}

export default RouteSwitch;
  • index.js*
import React from 'react';
import ReactDOM from 'react-dom/client';
import RouteSwitch from "./routeswitch"
import './index.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <RouteSwitch/>
  </React.StrictMode>
);
  • item.test.js*
import React from 'react';
import { render, cleanup,screen, getByAltText} from '@testing-library/react';
import '@testing-library/jest-dom'
import userEvent from '@testing-library/user-event';
import Item from './item';

afterEach(cleanup);
const details = {pic: `a pic`, title:`a title`, description:`a description`}
const addCartMock =jest.fn(); 

test(`Content renders`,()=>{
  render(<Item info={details} addCart={addCartMock}/>);

  const image = screen.getByAltText(`${details.title}`);
  expect(image).toBeInTheDocument();
  expect(image).toHaveAttribute(`src`,`${details.pic}`);
  expect(screen.getByRole(`heading`, {name:details.title})).toBeInTheDocument();
  expect(screen.getByText(`${details.description}`)).toBeInTheDocument();
  expect(screen.getByRole(`button`, {name: `Add`})).toBeInTheDocument();
});

test(`Add button click event`,()=>{
  render(<Item info={details} addCart={addCartMock(details)}/>);

  userEvent.click(screen.getByRole(`button`), {name: `Add`});
  expect(addCartMock).toHaveBeenCalledWith(details);
});
piztneat

piztneat1#

单元测试中Link的问题是它需要提供路由上下文。导入MemoryRouter并将组件渲染到其中,以便Link组件具有可用的路由上下文。
示例:

import React from 'react';
import { render, cleanup, screen, getByAltText } from '@testing-library/react';
import '@testing-library/jest-dom';
import userEvent from '@testing-library/user-event';
import { MemoryRouter } from 'react-router-dom';
import Item from './item';

afterEach(cleanup);

const details = {
  pic: "a pic",
  title: "a title",
  description: "a description",
};
const addCartMock = jest.fn(); 

test("Content renders", () => {
  render(
    <MemoryRouter>
      <Item info={details} addCart={addCartMock} />
    </MemoryRouter>
  );

  const image = screen.getByAltText(`${details.title}`);
  expect(image).toBeInTheDocument();
  expect(image).toHaveAttribute("src",`${details.pic}`);
  expect(screen.getByRole("heading", { name: details.title })).toBeInTheDocument();
  expect(screen.getByText(`${details.description}`)).toBeInTheDocument();
  expect(screen.getByRole("button", { name: `Add` })).toBeInTheDocument();
});

test("Add button click event", () => {
  render(
    <MemoryRouter>
      <Item info={details} addCart={() => addCartMock(details)} />
    </MemoryRouter>
  );

  userEvent.click(screen.getByRole("button"), { name: "Add" });
  expect(addCartMock).toHaveBeenCalledWith(details);
});

Item组件中访问props对象也有问题。只有一个props对象传递给React组件,所有props都是从它解构的。

const Item = ({ info, addCart }) => {
  return (
    <>
      <Link to="/"><button>X</button></Link>
      <img src={info.pic} alt={info.title} />
      <h1>{info.title}</h1>
      <p>{info.description}</p>
      <button onClick={()=>{addCart(info)}}>Add</button>
    </>
  );
};
hc8w905p

hc8w905p2#

不确定是不是它导致了这个问题,但是在你的item.js中,你错误地解构了props。你可以直接解构它,或者使用props并使用点符号来获得它的孩子:

const Item = ({info, addCart}) => {

  return(
    <>
      // rest of your code
    </>
  )
};

const Item = (props) => {

  return(
    <>
      <Link to="/" ><button>X</button></Link>
      <img src={props.info.pic} alt={props.info.title}></img>
      <h1>{props.info.title}</h1>
      <p>{props.info.description}</p>
      <button onClick={()=>{props.addCart(info)}}>Add</button>
    </>
  )
};

const Item = (props) => {
  const {info, addCart} = props
  return(
    <>
      <Link to="/" ><button>X</button></Link>
      <img src={info.pic} alt={info.title}></img>
      <h1>{info.title}</h1>
      <p>{info.description}</p>
      <button onClick={()=>{addCart(info)}}>Add</button>
    </>
  )
};

相关问题