My React app has an Item
component that should redirect users to the App
component by clicking a button inside a react-router-dom
Link
component. I’ve followed lots of tutorials that have given clear examples of how to implement Link
inside components that don’t pass props. My guts tell me that my Item
component props might be causing the Cannot destructure property 'basename' of 'React__namespace.useContext(...)' as it is null.]
error because running tests on Jest are only possible when Link
is not present in the code.
What I tried
- Moved the
RouteSwitch
code to index.js - Moved the scripts that live in the
components
tosrc
- Double-checked that I followed the tutorials correctly
- Saw if this reactjs – Uncaught TypeError StackOverFlow answer is related to my problem
Can anybody point out what I’m missing here please?
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);
});
2
Answers
The issue with the
Link
in the unit tests is that it requires a routing context to be provided to it. Import theMemoryRouter
and render the component into it so theLink
component has a routing context available to it.Example:
You’ve also an issue accessing the props object in the
Item
component. There is only a single props object passed to React components and all props are destructured from it.Not sure if it’s what is causing the challenge, but in your
item.js
you are destructuring the props wrongly. you can either desructure it directly, or take the props and use dot notations to get its children:OR
OR