Mastering Jest Configuration for React TypeScript Projects with Vite: A Step-by-Step Guide
Tags: jest, vite, react, testing
Published: 2023-12-15 18:27:34


## 1. First generate react typescript using vite

```sh
npm create vite@latest
```

## 2. Install dependancies

```sh
npm i jest @types/jest ts-jest --save-dev
```

## 3. Exclude test files from typescript type checking for production

- Create tsconfig.prod.json and paste following contents into it.

```sh
touch tsconfig.prod.json
```

```js
// tsconfig.prod.json
{
  "extends": "./tsconfig",
  "exclude": [
    "./src/__tests__/**",
    "./src/__mocks__/**",
    "./src/test-utils"
  ]
}

```

<blockquote cite="https://hung.dev/posts/jest-vite">
<p>Exclude test files from typescript type checking when building for production, you don’t want a typescript error in your test file breaks your build in production.
</p>
  <footer>—Nguyen Viet Hung, <cite>hung.dev</cite></footer>
</blockquote>

<br >

- Use `tsconfig.prod.json` when building

```sh
# package.json
{
...,
"scripts":{
  ...,
  "build": "NODE_ENV=production tsc -p tsconfig.prod.json && vite build"
},
...
}
```

## 4. Add `test` script to `package.json`

```js
// package.json
{
...,
"scripts":{
  ...,
  "test": "NODE_ENV=test jest"
},
...
}
```

## 5. Write a simple test

```js
// src/App.test.tsx

describe('App', () => {
  it('should work as expected', () => {
    expect(1 + 1).toBe(2);
  });
});
```

Run the `npm run test` 🤞, and first test case 😃 passed. 🚀

```sh
node 'node_modules/.bin/jest' '/.../code/my-doc-test-app/src/App.test.tsx' -t 'App'
 PASS  src/App.test.tsx
  App
    ✓ should work as expected (1 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.209 s
Ran all test suites matching /...\/code\/my-doc-test-app\/src\/App.test.tsx/i with tests matching "App".

```

## 6. Test the `App` component

```js
// src/App.test.tsx
import { render } from '@testing-library/react';
import App from './App';

describe('App', () => {
  it('should work as expected', () => {
    render(<App />);
  });
});
```

Run the `npm run test` 🤞, and test failed. This error will show up.

```sh
node 'node_modules/.bin/jest' '/Users/satparkash/code/test-app/src/A
pp.test.tsx' -t 'App'
 FAIL  src/App.test.tsx
  ● Test suite failed to run

    SyntaxError: /Users/satparkash/code/test-app/src/App.test.tsx: Support for the experimental syntax 'jsx' isn't currently enabled (6:12):

      4 | describe('App', () => {
      5 |   it('should work as expected', () => {
    > 6 |     render(<App />);
        |            ^
      7 |   });
      8 | });
      9 |

    Add @babel/preset-react (https://github.com/babel/babel/tree/main/packages/babel-preset-react) to the 'presets' section of your Babel config to enable transformation.
    If you want to leave it as-is, add @babel/plugin-syntax-jsx (https://github.com/babel/babel/tree/main/packages/babel-plugin-syntax-jsx) to the 'plugins' section to enable parsing.

    Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.278 s
Ran all test suites matching /\/Users\/satparkash\/code\/test-app\/src\/App.test.tsx/i with tests matching "App".

```

The above ☝️ error message is indicating a syntax related to `JSX` in test file.
The error is saying that support for the syntax 'JSX' isn't currently enabled.

To resolve the issue we need to make sure that the `JSX` syntax is properly
configured for project, and also the `jest`. **(Hint: Babel)**

## 7. For JSX support, add babel presets and add .babelrc

- Firstly Install dependancies

```sh
npm i @babel/preset-env @babel/preset-react @babel/preset-typescript --save-dev
```

- Create `.babelrc` file at project root, and paste following contents into it.

```sh
touch .babelrc
```

```js
//.babelrc
{
  "presets": [
    "@babel/preset-env",
    ["@babel/preset-react", { "runtime": "automatic" }],
    "@babel/preset-typescript"
  ]
}
```

## 8. Install testing library for react

By Now previous error will be gone and you will get new error message.

```sh
node 'node_modules/.bin/jest' '/Users/satparkash/code/test-app/src
/App.test.tsx' -t 'App'
 FAIL  src/App.test.tsx
  ● Test suite failed to run

    Cannot find module '@testing-library/react' from 'src/App.test.tsx'

    > 1 | import { render } from '@testing-library/react';
        | ^
      2 | import App from './App';
      3 |
      4 | describe('App', () => {

      at Resolver._throwModNotFoundError (node_modules/jest-resolve/build/resolver.js:427:11)
      at Object.require (src/App.test.tsx:1:1)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.231 s
Ran all test suites matching /\/Users\/satparkash\/code\/test-app\/src\/App.test.tsx/i with tests matching "App"

```

<blockquote cite="https://maous.medium.com/setup-testing-environment-for-react-typescript-with-jest-1f5eb453aa2">
<p>Now, you have to add libraries which will allow you to make things happen (access VDOM, interacting …. etc), And those libraries are “@testing-library/dom”, “@testing-library/jest-dom”, “@testing-library/react” and “@testing-library/user-event”</p>
  <footer>—Mhand</footer>
</blockquote>

<br>

```sh
npm i @testing-library/dom @testing-library/jest-dom @testing-library/react @testing-library/user-event --save-dev
```

Now it's time to configure jest-environment. You will see another error message
saying `Jest encountered an unexpected token`, don't worry we are about to fix
it.

## 9. Let's Configure Jest

- Firstly install following dependancies

```sh
npm i ts-node jest-environment-jsdom --save-dev
```

- Create a file `jest.config.ts` at the root project, and paste following
  contents into it.

```sh
touch jest.config.ts
```

```js
//jest.config.ts
export default {
  rootDir: 'src',
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  transform: {
    '^.+\\.tsx?$': 'ts-jest',
    // process `*.tsx` files with `ts-jest`
  },
  moduleNameMapper: {
    '\\.(gif|ttf|eot|svg|png)$': '<rootDir>/config/jest/fileMock.ts',
    '^.+\\.(css|less|scss|sass)$': '<rootDir>/config/jest/styleMock.ts',
  },
  setupFilesAfterEnv: ['./config/jest/setupTests.ts'],
  moduleFileExtensions: [
    // Place tsx and ts to beginning as suggestion from Jest team
    // https://jestjs.io/docs/configuration#modulefileextensions-arraystring
    'tsx',
    'ts',
    'web.js',
    'js',
    'web.ts',
    'web.tsx',
    'json',
    'web.jsx',
    'jsx',
    'node',
  ],
  modulePaths: ['<rootDir>/src'],
};
```

- Create `config/jest/styleMock.ts`, `config/jest/fileMock.ts` to mock css and
  files.

```js
// config/jest/styleMock.ts

module.exports = {};
```

```js
// config/jest/fileMock.ts

export {}; //coment this if you ts-node to start complaining again
module.exports = 'test-file-stub';
```

- Create `config/jest/setupTests.ts`, a file that runs before each test.

```js
//config/jest/setupTests.ts

// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';
```

> INFO

```js
/**
 *
 * If imported(inside setupTests.ts):
 * import '@testing-library/jest-dom/extend-expect'
 * then we are required to map it inside `jest.config.ts` like this:
 * 
 
 * // jest.config.ts
 * {
 * ...,
 * moduleNameMapper: {
 * ...,
 *     '@testing-library/jest-dom/extend-expect': '@testing-library/jest-dom',
 * }
 * }
 */
```

By this moment, you can run the test successfully😎.

```sh
node 'node_modules/.bin/jest' '/Users/satparkash/code/test-app/src/App.test.tsx' -t 'App'
 PASS  src/App.test.tsx
  App
    ✓ should work as expected (12 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.19 s
Ran all test suites matching /\/Users\/satparkash\/code\/test-app\/src\/App.test.tsx/i with tests matching "App".
```

Happy testing 😀

---

## 10. For Snapsot Testing [optional]

For snapshot testing add react-test-renderer

```sh
npm i react-test-renderer --save-dev
```

> PS: I didnt' implemented snapshot testing 😄 Yet.

## 11. For import.meta' meta-property is only allowed when the '--module' option is... [error TS1343]

- Error Message

```sh
error TS1343: The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'es2022', 'esnext', 'system', 'node16', or 'nodenext'.

          .get(import.meta.env.VITE_API_PATH + '/api/posts')

```

- Install dependancy

```sh
npm install -D ts-jest-mock-import-meta
```

- Change the transform to mock `import.meta` of vite

```js
// jest.config.ts

export default {

  ...,
    transform: {
    '^.+\\.tsx?$': [
      'ts-jest',
      {
        diagnostics: {
          ignoreCodes: [1343],
        },
        astTransformers: {
          before: [
            {
              path: 'node_modules/ts-jest-mock-import-meta',
              options: {
                metaObjectReplacement: {
                  env: {
                    // Replicate as .env.local
                    VITE_API_PATH: 'http://localhost:3001',
                  },
                },
              },
            },
          ],
        },
      },
    ],
  },
  ...
}

```

### References

- [Setup Jest with Vite (featuring SWC)](https://hung.dev/posts/jest-vite)
- [Setup Testing Environment for React/TypeScript with Jest ! ](https://maous.medium.com/setup-testing-environment-for-react-typescript-with-jest-1f5eb453aa2)
- [Installing Jest for Testing in Your Vite-React TypeScript Project. A Step-by-Step Guide.](https://dev.to/hannahadora/jest-testing-with-vite-and-react-typescript-4bap)
- [How to setup Jest and React Testing Library in Vite project ](https://zaferayan.medium.com/how-to-setup-jest-and-react-testing-library-in-vite-project-2600f2d04bdd)
- [ChatGPT](https://chat.openai.com/share/a9f98f2c-a707-4272-b788-32845fe4b395)
- [The 'import.meta' meta-property is only allowed when the '--module' option is 'es2020', 'es2022', 'esnext', 'system', 'node16', or 'nodenext'.](https://github.com/kulshekhar/ts-jest/issues/3888)