Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a (Zustand) function mock with Jest results in "TypeError: create is not a function"

I'm following the Zustand wiki to implement testing, but the provided solution is not working for a basic test for app rendering. My project is built on top of the Electron React Boilerplate boilerplate project.

Here's the full error. Jest is using node with experimental-vm-modules because I followed the the Jest docs to support ESM modules.

$ cross-env NODE_OPTIONS=--experimental-vm-modules jest
(node:85003) ExperimentalWarning: VM Modules is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
jest-haste-map: Haste module naming collision: myproject
  The following files share their name; please adjust your hasteImpl:
    * <rootDir>/package.json
    * <rootDir>/src/package.json

 FAIL  src/__tests__/App.test.tsx
  ● Test suite failed to run

    TypeError: create is not a function

      12 | }
      13 |
    > 14 | const useNotifs = create<NotifsState>(
         |                   ^
      15 |   // devtools(
      16 |   (set) => ({
      17 |     notifStore: notifsDefault.notifStore,

      at src/state/notifs.ts:14:19
      at TestScheduler.scheduleTests (node_modules/@jest/core/build/TestScheduler.js:333:13)
      at runJest (node_modules/@jest/core/build/runJest.js:387:19)
      at _run10000 (node_modules/@jest/core/build/cli/index.js:408:7)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        11.882 s
Ran all test suites.
error Command failed with exit code 1.

At the top of the notifs.ts file, Zustand is imported normally with import create from 'zustand'.

Jest config in package.json:

    ...
    "moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/config/mocks/fileMock.js",
      "\\.(css|less|sass|scss)$": "identity-obj-proxy",
      "zustand": "<rootDir>/src/__mocks__/zustand.js",
    },
    "transformIgnorePatterns": [
      "node_modules/(?!(zustand)/)",
      "<rootDir>/src/node_modules/"
    ],
    "moduleDirectories": [
      "node_modules",
      "src/node_modules"
    ],
    "moduleFileExtensions": [
      "js",
      "jsx",
      "ts",
      "tsx",
      "json"
    ],
    "moduleDirectories": [
      "node_modules",
      "src/node_modules"
    ],
    "extensionsToTreatAsEsm": [
      ".ts",
      ".tsx"
    ],

    ...

I have left the ./src/__mocks__/zustand.js file exactly the same as from the Zustand wiki Testing page. I receive the same error whether or not I have zustand in the transformIgnorePatterns.

My Babel configuration includes [require('@babel/plugin-proposal-class-properties'), { loose: true }], in the plugins section, and output.library.type is 'commonjs2'

My tsconfig.json has compilerOptions.module set to "CommonJS", and the project's package.json "type" field is set to "commonjs".

Dependency versions:

    "@babel/core": "^7.12.9",
    "@babel/preset-env": "^7.12.7",
    "@babel/preset-react": "^7.12.7",
    "@babel/preset-typescript": "^7.12.7",
    "@babel/register": "^7.12.1",
    "@babel/plugin-proposal-class-properties": "^7.12.1",
    "@testing-library/jest-dom": "^5.11.6",
    "@testing-library/react": "^11.2.2",
    "babel-jest": "^27.0.6",
    "babel-loader": "^8.2.2",
    "jest": "^27.0.6",
    "regenerator-runtime": "^0.13.9",
    "source-map-support": "^0.5.19",
    "typescript": "^4.0.5",
    "webpack": "^5.5.1",
    "zustand": "^3.5.5"

I don't know what else could be relevant, just let me know if anything else is needed. Any and all help appreciated, thanks for your time.

like image 204
fowl- Avatar asked Mar 03 '26 20:03

fowl-


2 Answers

To do this you should use the actual store of your app

const initialStoreState = useStore.getState()
 
 beforeEach(() => {
    useStore.setState(initialStoreState, true)
  })

useStore.setState({ me: memberMockData, isAdmin: true })

The documentation seems off. So don't follow it.

like image 92
Bon Andre Opina Avatar answered Mar 05 '26 12:03

Bon Andre Opina


Looks similar to the error I came across:

    TypeError: store.getState is not a function

   9 | export const create = <S>(createState: StateCreator<S>) => {
  10 |      const store = actualCreate(createState);
> 11 |      const initialState = store.getState();
     |                                 ^
  12 |      storeResetFns.add(() => store.setState(initialState, true));
  13 |      return store;
  14 | };

In my case, it was caused by not currying the create function like so:

               👇
const create = () => <S>(createState: StateCreator<S>) => {
  const store = actualCreate(createState);
  const initialState = store.getState();
  storeResetFns.add(() => store.setState(initialState, true));
  return store;
};

See this issue.

like image 24
grigol Avatar answered Mar 05 '26 10:03

grigol



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!