ts-jest is a godsend, use it.

Configuration (+ monorepo extensibility)

import type { Config } from 'jest';

const config: Config = {
  collectCoverage: false,
  collectCoverageFrom: ['src/**/*.ts', 'src/**/*.tsx'],
  preset: 'ts-jest',
  setupFiles: [],
  setupFilesAfterEnv: [],
  testEnvironment: 'node',
  testPathIgnorePatterns: ['/node_modules/', '/dist/'],
  verbose: true,
};

export default config;
import type { Config } from 'jest';

import rootJestConfig from '../../jest.config';

const config: Config = {
  ...rootJestConfig,
  setupFiles: [
    ...(rootJestConfig.setupFiles ?? []),
  ],
  setupFilesAfterEnv: [
    ...(rootJestConfig.setupFilesAfterEnv ?? []),
    '<rootDir>/.jest/setup-files-after-env/before-each.ts',
  ],
};

export default config;

beforeEach > jest.clearAllMocks()

Will need to create this file for each package in the monorepo.

beforeEach(async () => {
  /**
   * Here's a good explaination of the clear/reset methods on `jest`: <https://dev.to/edwinwong90/jestclearallmocks-vs-jestresetallmocks-vs-jestrestoreallmocks-explained-5aal>
   *
   * jest.clearAllMocks: "Clear all mock usage data such as mock.calls, mock.instances, mock.contexts and mock.results but not their implementation."
   * jest.resetAllMocks: "A superset of clearAllMocks() and it also reset the mock function implementations with brand new jest.fn()."
   * jest.restoreAllMocks: "Restore all mock back to their original implementation and it only works for mock was created with jest.spyOn."
   *
   * With this in mind, we'll always be interested in `clearAllMocks` to run between each individual test. If we ever move to a setup where
   * we want mock states persist between tests, we'll need to modify this piece of code.
   */
  jest.clearAllMocks();
});