Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot unit test components which use <Link /> due to missing Router context #4506

Closed
kwiat1990 opened this issue Nov 3, 2022 · 4 comments
Closed
Labels
bug:unverified duplicate This issue or pull request already exists

Comments

@kwiat1990
Copy link

kwiat1990 commented Nov 3, 2022

What version of Remix are you using?

1.7.4

Steps to Reproduce

Use test setup from Blues Stack:

// setup-test-env.ts
import { installGlobals } from "@remix-run/node";
import "@testing-library/jest-dom/extend-expect";

installGlobals();

Use Vitest 0.24.4 (perhaps Jest also) and write a simple unit test for a pure react component, which uses <Link /> component from @remix-run/react.

Current test:

// tags.test.tsx
describe("<Tags />", () => {
  it("renders list of links", () => {
    render(<Tags />);
    expect(screen.getAllByRole("link").length).toBeGreaterThan(0);
  });
});

I saw that one could pass additional config to render function with the actual router component as follows:

// tags.test.tsx

// replace 
render(<Tags />);

// with
render(<Tags />, { wrapper: BrowserRouter });

The problem is that in this case BrowserRouter must be imported from react-router-dom package, which we don't need in a Remix app. But even with this approach, after adding this package to dev dependency, it doesn't solve the issue. Importing RemixBrowser doesn't work either, but due to other errors.

For some reason, the second approach (wrapping component with react router's BrowserRouter) seems to work after changing environment option in vitest.config.ts from happy-dom to jsdom.

Expected Behavior

Test is green.

Actual Behavior

app/components/tags.test.tsx > <Tags /> > renders list of links
Error: useHref() may be used only in the context of a <Router> component.
 ❯ invariant ../packages/react-router/lib/router.ts:5:20
 ❯ Object.useHref ../packages/react-router/lib/hooks.tsx:32:3
 ❯ node_modules/@remix-run/react/dist/components.js:390:29
 ❯ renderWithHooks node_modules/react-dom/cjs/react-dom.development.js:16305:18
 ❯ updateForwardRef node_modules/react-dom/cjs/react-dom.development.js:19226:20
 ❯ beginWork node_modules/react-dom/cjs/react-dom.development.js:21636:16
 ❯ HTMLUnknownElement.callCallback node_modules/react-dom/cjs/react-dom.development.js:4164:14
 ❯ HTMLUnknownElement.dispatchEvent node_modules/happy-dom/src/event/EventTarget.ts:66:41
 ❯ HTMLUnknownElement.dispatchEvent node_modules/happy-dom/src/nodes/node/Node.ts:477:29
 ❯ Object.invokeGuardedCallbackDev node_modules/react-dom/cjs/react-dom.development.js:4213:16
 ❯ invokeGuardedCallback node_modules/react-dom/cjs/react-dom.development.js:4277:31
 ❯ beginWork$1 node_modules/react-dom/cjs/react-dom.development.js:27451:7
 ❯ performUnitOfWork node_modules/react-dom/cjs/react-dom.development.js:26560:12
 ❯ workLoopSync node_modules/react-dom/cjs/react-dom.development.js:26466:5
 ❯ renderRootSync node_modules/react-dom/cjs/react-dom.development.js:26434:7
 ❯ recoverFromConcurrentError node_modules/react-dom/cjs/react-dom.development.js:25850:20
 ❯ performConcurrentWorkOnRoot node_modules/react-dom/cjs/react-dom.development.js:25750:22
 ❯ flushActQueue node_modules/react/cjs/react.development.js:2667:24
 ❯ act node_modules/react/cjs/react.development.js:2582:11
 ❯ node_modules/@testing-library/react/dist/act-compat.js:63:25
 ❯ renderRoot node_modules/@testing-library/react/dist/pure.js:159:26
 ❯ Proxy.render node_modules/@testing-library/react/dist/pure.js:246:10
 ❯ app/components/tags.test.tsx:26:4
     24|   it("renders list of links", () => {
     25|     // render(<Tags tags={mockTags} />, { wrapper: BrowserRouter });
     26|     render(<Tags tags={mockTags} />);
       |    ^
     27|     expect(screen.getAllByRole("link").length).toBe(3);
     28|   });
@kwiat1990 kwiat1990 changed the title Cannot unit test components which use <Link /> - missing Router context Cannot unit test components which use <Link /> due to missing Router context Nov 3, 2022
@jrestall
Copy link
Contributor

jrestall commented Nov 4, 2022

The team are working on official testing helpers on their backlog. In the meantime you should read through Ryan's createRemixStub design here and there's a sample implementation you can copy + paste here.

@machour
Copy link
Collaborator

machour commented Nov 5, 2022

Closing this issue as it's already tracked in #4488

@machour machour closed this as not planned Won't fix, can't repro, duplicate, stale Nov 5, 2022
@MichaelDeBoey MichaelDeBoey added the duplicate This issue or pull request already exists label Nov 5, 2022
@kwiat1990
Copy link
Author

The team are working on official testing helpers on their backlog. In the meantime you should read through Ryan's createRemixStub design here and there's a sample implementation you can copy + paste here.

Thanks for pointing this out. I did saw the discussion and even your repo but to be honest, I though it's more relevant to all cases, in which loader or actions need to be tested. Nevertheless, I gave it a try and yep, it does work for me. I assume with this setup I can now even test pages to some degree.

@jrestall
Copy link
Contributor

jrestall commented Nov 5, 2022

The team are working on official testing helpers on their backlog. In the meantime you should read through Ryan's createRemixStub design here and there's a sample implementation you can copy + paste here.

Thanks for pointing this out. I did saw the discussion and even your repo but to be honest, I though it's more relevant to all cases, in which loader or actions need to be tested. Nevertheless, I gave it a try and yep, it does work for me. I assume with this setup I can now even test pages to some degree.

Glad it's working for you! Yes you should be able to test everything jsdom supports, main limitations are browser navigations are best left to playwright/cypress and form submissions have a few bugs in jsdom. You can test the rendering of entire nested routes though as shown here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug:unverified duplicate This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

4 participants