Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No "BrowserRouter" export is defined on the "/node_modules/react-router-dom/dist/main.js" mock. Did you forget to return it from "vi.mock"?

I'm testing a simple React component using Vitest. This is the function that renders my component: (the server stuff is MSW)

function renderComponent() {
  render(<Router initialEntries={['/entry-detail']}> <SnackbarProvider>
    <EntryDetail />
  </SnackbarProvider>
  </Router>
  );
}

This is my test:

describe('EntryDetail component', () => {
  beforeAll(() => server.listen());
  afterEach(() => server.resetHandlers());
  afterAll(() => server.close());

  vi.mock('react-router-dom', () => ({
    useParams: () => ({
      articleId: '63d466ca3d00b50db15aed93',
    }),
  }));

  it('allows only 150 characters for comments', async () => {
    authorizedServerSetup();
    renderComponent();
    // const commentInput = await screen.findByRole('textbox');
    // console.log(commentInput);
  });
});

This is the error message that I get which I don't understand: enter image description here

Error: [vitest] No "BrowserRouter" export is defined on the "/node_modules/react-router-dom/dist/main.js" mock. Did you forget to return it from "vi.mock"?

Following the advice on the console didn't make any difference. I tried using MemoryRouter as well, no difference. What's going on? How do I test this?

The component to be tested is the following:

export const EntryDetail = () => {
  const { articleId } = useParams();
  const [article, setArticle] = useState({ title: null, body: null, comments: [], likes: [] });
  const { title, body, comments, likes, image } = article;

  useEffect(() => {
    (async () => {
      try {
        const response = await getArticleDetail(articleId);
        const { title, body, comments, likes, image } = response.data;
        setArticle({ title, body, comments, likes, image });
      } catch (e) {
        console.error(e);
      }
    })();
  }, []);

  return (
    <Container>
      {
        !article.title
          ? <div style={{ textAlign: 'center' }}>Loading...</div>
          : <>
            <Title>{title}</Title>
            <img src={image} />
            <p className="body">{body}</p>
            <ReactionBar {...{ likes, articleId }} />
            <CommentsSection {...{ comments, articleId }} />
          </>
      }

    </Container>
  );
};

I also tried something like this:

vi.mock('react-router-dom', async (importOriginal) => {
  const mod = await importOriginal();
  return {
    ...mod,
    useParams: () => ({
      articleId: '63d466ca3d00b50db15aed93',
    }),
  };
});

But I'm getting basically the same error: enter image description here

like image 743
Daniel Tkach Avatar asked Oct 16 '25 01:10

Daniel Tkach


1 Answers

For anyone else struggling with this, the issue is that you need to mock the BrowserRouter in addition to the useParams hook. To do that, you need to first import BrowserRouter from 'react-router-dom'

import { BrowserRouter as Router } from "react-router-dom";

And then add it to the callback of the vi.mock method like so:

 vi.mock('react-router-dom', () => ({
    useParams: () => ({
      articleId: '63d466ca3d00b50db15aed93',
    }),
    BrowserRouter: vi.fn().mockImplementation((props) => props.children),
  }));

Then you can use your component in a test as you normally would :)

like image 76
sarahm16 Avatar answered Oct 18 '25 18:10

sarahm16