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

Jest/Vitest unit testing: TypeError: (0 , _reactdom.useFormStatus) is not a function #63868

Open
SunDevils0 opened this issue Mar 29, 2024 · 7 comments
Labels
bug Issue was opened via the bug report template. Testing Related to testing with Next.js. TypeScript Related to types with Next.js.

Comments

@SunDevils0
Copy link

Link to the code that reproduces this issue

https://github.com/SunDevils0/with-jest-app

To Reproduce

  1. Followed Next js instructions on creating project with jest: https://nextjs.org/docs/app/building-your-application/testing/jest#optional-extend-jest-with-custom-matchers
  2. In my app folder, created a very simple button component. Copied/pasted the same code from the Next JS documentation on useFormStatus.
  3. Within the same components folder, added a test file and wrote my unit test: button.test.tsx. The only thing the test does is render the button (the only thing needed to recreate this issue).
  4. Run tests; error received.

Current vs. Expected behavior

Current
Receive error: TypeError: useFormStatus is not a function

Expected
No error received and rest of test able to be evaluated.

Provide environment information

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 10 Enterprise
Binaries:
  Node: 20.11.0
  npm: N/A
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 14.1.1
  eslint-config-next: N/A
  react: 18.2.0
  react-dom: 18.2.0
  typescript: N/A
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Jest (next/jest), TypeScript (plugin, built-in types)

Which stage(s) are affected? (Select all that apply)

next dev (local)

Additional context

  • If I modify the button component and remove the useFormStatus hook, the test will pass.
  • When creating the next with jest project, many of the packages were not at the latest version. Error occurs in this "initial" state, with all packages updated (environment information was taken at this point), and when upgrading next to latest canary.
  • To be clear, I have no problems with these hooks when I run my application. Such issues have been previously reported and, from what I found in my Internet searches, resolved. But none of those issues I found were specific to testing.
  • I am new to NextJs/React/TypeScript, and my first project is using Vitest as the test framework. To eliminate user error - my initial thought - this morning I created as bare-bones projects as possible, one using jest (the repo linked in this issue) and the other Vitest: https://github.com/SunDevils0/next-poc-for-unit-testing-error. The Vitest had a few more manual steps in setting up. I get this issue in both. These are the only testing frameworks I have tried in recreating the issue.
  • I also get the same error in my work Vitest project with useFormState. (I know this is being replaced with useActionState.)
@SunDevils0 SunDevils0 added the bug Issue was opened via the bug report template. label Mar 29, 2024
@github-actions github-actions bot added Testing Related to testing with Next.js. TypeScript Related to types with Next.js. labels Mar 29, 2024
@jthrilly
Copy link

jthrilly commented Apr 18, 2024

I get these same types of errors when my tests touch code that contains React.cache. This is included in the internal React version Next is using, but not in the 18.2 release of React itself. It seems like the module resolution that is used by vitest (and presumably jest) isn't the same as whatever Next is doing.

Edit: created an issue for my case of this: #64783

@rylew1
Copy link

rylew1 commented May 4, 2024

Was this ever resolved ? Got a similar error Error: Uncaught [TypeError: (0 , _reactdom.useFormStatus) is not a function] in a simple jest test.

When I remove uses of useFormStatus in source files, the tests pass.

@AhmedBaset
Copy link
Contributor

useFormStatus is not available in react-dom@18.2.0 (the version in your package.json). It's available in React Canary/Beta/Experimental chanels. To solve it you can:

  • npm i react@canary react-dom@canary
  • wait until react@19 is released as stable
  • mock useFormStatus until the release.

Note

Next.js doesn't use the react version in your package.json, it uses a pre-compiled canary version. Updating react (or even removing it) will only affect tests.

@SunDevils0
Copy link
Author

Thanks. Successfully implemented the first and third option. For the third, which is what I will be using for projects I am currently working:

import { render, screen } from '@testing-library/react';
import Button from './button';
import { useFormStatus } from 'react-dom';

jest.mock('react-dom', () => ({
    useFormStatus: jest.fn(),
}));

describe('Button', () => {
    it('should render label', () => {
        // Arrange
        const label = 'Button';
        (useFormStatus as jest.Mock).mockResolvedValue(true);
        render(<Button type="button" label={label} />);

        // Act and Assertions ...
    });
});

@SunDevils0
Copy link
Author

Just to set expectations, the code I posted last night mocking useFormStatus just prevents the error. The test I was originally working on when posting this issue doesn't care about useFormStatus or its parameter values. Later I did try a test where I destructured the mock to set the pending parameter to be true. I could not get this to work. Stepping through the code pending always shows undefined.

// Arrange
const label = 'Button';
(useFormStatus as jest.Mock).mockResolvedValue({ pending: true });
render(
    <form action=""> // 
        <Button
            type="button"
            label={label}
        />
    </form>
);

Have to move along to other priorities, but if I do find a way to make this usable in a test will post here.

@JarrettD5309
Copy link

useFormStatus is not available in react-dom@18.2.0 (the version in your package.json). It's available in React Canary/Beta/Experimental chanels. To solve it you can:

  • npm i react@canary react-dom@canary
  • wait until react@19 is released as stable
  • mock useFormStatus until the release.

Note

Next.js doesn't use the react version in your package.json, it uses a pre-compiled canary version. Updating react (or even removing it) will only affect tests.

Installing canary versions of react and react-dom worked for me! And a big thank you for your note as I am always wary of creating larger unforeseen issues by correcting an issue at hand.

@fabriziosta
Copy link

I was able to mock useFormStatus only like this:

const { useFormStatus } = require('react-dom');
jest.mock('react-dom', () => {
  return {
    ...jest.requireActual('react-dom'),
    useFormStatus: jest.fn(),
  };
});
useFormStatus.mockImplementation(() => ({
  pending: false,
  data: null,
  method: null,
  action: null,
}));

Paste it on top of your test file and it should work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template. Testing Related to testing with Next.js. TypeScript Related to types with Next.js.
Projects
None yet
Development

No branches or pull requests

6 participants