@repobuddy/jest
v4.1.1
Published
Your jest buddy
Downloads
1,089
Readme
@repobuddy/jest
@repobuddy/jest provides tools and utilities to manage your jest usage, so you don't have to.
Turn your config from this:
export default {
collectCoverageFrom: ['<rootDir>/ts/**/*.{js,jsx,cjs,mjs,ts,tsx,cts,mts}'],
coveragePathIgnorePatterns: [
/* ... */
],
extensionsToTreatAsEsm: ['.ts', '.tsx', '.mts'],
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
/* ... and the ESM madness like `chalk` ... */
},
testEnvironment: 'node',
testRegex: [
/* ... */
],
roots: ['<rootDir>/ts'],
transform: {
'^.+\\.(ts|tsx|cts|mts)$': ['ts-jest', [{
isolatedModules: true,
useESM: true,
diagnostics: {
// https://github.com/kulshekhar/ts-jest/issues/3820
ignoreCodes: [151001]
}
}]],
'\\.m?jsx?$': 'jest-esm-transformer-2',
/* ... more ESM madness ... */
},
transformIgnorePatterns: [],
watchPlugins: [
'jest-watch-suspend',
['jest-watch-toggle-config-2', { setting: 'collectCoverage' }],
['jest-watch-toggle-config-2', { setting: 'verbose' }],
'jest-watch-typeahead/filename',
'jest-watch-typeahead/testname'
]
}
to this:
export default {
preset: '@repobuddy/jest/presets/ts-esm-watch'
}
Install
# npm
npm install -D @repobuddy/jest
# yarn
yarn add -D @repobuddy/jest
# pnpm
pnpm add -D @repobuddy/jest
# rush
rush add -p @repobuddy/jest --dev
Upgrading to ts-jest
29.2
If you are using ts-jest
29.2 or above,
you may run into the Cannot use import statement outside a module
error.
For example:
/home/unional/code/repobuddy/repobuddy/packages/jest/ts/presets/ts-watch/jest-preset.spec.ts:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { describe, expect, it } from '@jest/globals';
^^^^^^
SyntaxError: Cannot use import statement outside a module
This is because ts-jest
29.2 adds support for module: Node16/NodeNext
.
Presets
@repobuddy/jest comes with many presets:
@repobuddy/jest/presets/ts
: auto-detect if your project is CJS or ESM@repobuddy/jest/presets/ts-watch
: auto-detect if your project is CJS or ESM@repobuddy/jest/presets/ts-cjs
@repobuddy/jest/presets/ts-cjs-watch
@repobuddy/jest/presets/ts-esm
@repobuddy/jest/presets/ts-esm-watch
@repobuddy/jest/presets/js-cjs
@repobuddy/jest/presets/js-cjs-watch
@repobuddy/jest/presets/js-esm
@repobuddy/jest/presets/js-esm-watch
@repobuddy/jest/presets/jsdom-ts
: auto-detect if your project is CJS or ESM@repobuddy/jest/presets/jsdom-ts-watch
: auto-detect if your project is CJS or ESM@repobuddy/jest/presets/jsdom-ts-cjs
@repobuddy/jest/presets/jsdom-ts-cjs-watch
@repobuddy/jest/presets/jsdom-ts-esm
@repobuddy/jest/presets/jsdom-ts-esm-watch
@repobuddy/jest/presets/electron-ts
: auto-detect if your project is CJS or ESM@repobuddy/jest/presets/electron-ts-watch
: auto-detect if your project is CJS or ESM@repobuddy/jest/presets/electron-ts-cjs
@repobuddy/jest/presets/electron-ts-cjs-watch
@repobuddy/jest/presets/electron-ts-esm
@repobuddy/jest/presets/electron-ts-esm-watch
@repobuddy/jest/presets/electron-renderer-ts
: auto-detect if your project is CJS or ESM@repobuddy/jest/presets/electron-renderer-ts-watch
: auto-detect if your project is CJS or ESM@repobuddy/jest/presets/electron-renderer-ts-cjs
@repobuddy/jest/presets/electron-renderer-ts-cjs-watch
@repobuddy/jest/presets/electron-renderer-ts-esm
@repobuddy/jest/presets/electron-renderer-ts-esm-watch
@repobuddy/jest/presets/watch
: watch mode presets for multienvironment config
If you do not have any specific configs, these presets should work without additional configuration.
Here are some highlights:
- All presets will automatically detect your source folder (in either
src
,source
,ts
, orjs
). - Support platform specific tests:
feature.spec.node.ts
feature.spec.node16.ts
feature.spec.jsdom.ts
feature.spec.electron.ts
- uses @repobuddy/jest/resolver that handles subpath imports correctly.
cjs
uses jest-esm-transformer-2 to transforms ESM dependencies.ts
uses ts-jest withisolatedModule: true
.watch
uses these plugins by default:
Since your project will only use a specific config, none of these packages are marked as required peer dependencies. You will need to add them to your project manually.
There will be a CLI tool in the future to help simplify that. Contribution welcome! 🍺
If you want to make some adjustments based on a particular preset, you can import the preset and customize it like so:
import preset from '@repobuddy/jest/presets/ts-esm-watch'
export default {
preset: '@repobuddy/jest/presets/ts-esm-watch',
moduleNameMapper: {
...preset.moduleNameMapper,
// your customization
}
}
Besides customizing your config manually, @repobuddy/jest exposes everything it uses, so you can compose and customize them exactly the way you like.
Runners
@repobuddy/jest supports running jest in Node.js, jsdom, and electron.
For electron, you need to install the electron runner:
npm install -D @kayahr/jest-electron-runner
yarn add -D @kayahr/jest-electron-runner
pnpm add -D @kayahr/jest-electron-runner
Configs
The configurations for specific use cases are exposed and available for you to compose the exact config that you need.
They can be predefined configs:
or functions prefixed with config
:
Fields
Fields are predefined fields or functions about a particular field of the jest config.
They can be define
functions, which provides type assistants to define the particular field:
They can be known
configurations, which you can use to build your configuration easily:
- knownExtensionsToTreatAsEsm
- knownRunners
- knownTestEnvironments
- knownTestEnvironmentOptions
- knownTransforms
- knownWatchPlugins
Matchers
There are also matchers which you can use to extend the expect()
function:
- toSatisfies: Similar functionality provided by assertron and satisfier
Use expect.extend({ toSatisfier })
to add it to your expect()
function.
You can also do import '@repobuddy/jest/matchers'
in your setup to import them automatically.
Resolver
@repobuddy/jest/resolver fixes the ESM subpath imports issue by using resolve.imports.
So you don't need to do crazy hacks like:
export default {
moduleNameMapper: {
'#(.*)': '$1' // and this actually doesn't work in some cases
},
transformIgnorePatterns: [
'node_modules/(?!(chalk|#ansi-styles)/)'
]
}
or even
const path = require('node:path')
const chalk = require.resolve('chalk')
const chalkRootDir = chalk.slice(0, chalk.lastIndexOf('chalk'))
module.exports = {
// ...
moduleNameMapper: {
chalk,
'#ansi-styles': path.join(
chalkRootDir,
'chalk/source/vendor/ansi-styles/index.js',
),
'#supports-color': path.join(
chalkRootDir,
'chalk/source/vendor/supports-color/index.js',
)
}
}
Now, all you need is:
export default {
resolver: '@repobuddy/jest/resolver'
}
Or use one of the NodeJS presets!
Notes
Here are some notes about @repobuddy/jest that you may find useful.
ts-jest
: isolatedModules
By default, all ts
presets have isolatedModules
set to true
.
If you want to change that, you can override with the knownTransforms.tsJest*()
functions:
import { knownTransforms } from '@repobuddy/jest'
export default {
preset: '@repobuddy/jest/presets/ts-esm',
transform: knownTransforms.tsJest(/* your option */)
}
While you may want the type checking benefits, in my experience it is ok to break the types when you are in the middle of your code, e.g. when you are doing TDD.
I would recommend using the build process and IDE to help you to catch any type errors, while allowing the type to break while writing code and tests.
The tighter feedback loop makes it much easier to work with.
This also avoid getting the bad habit of marking things any
along the way,
just to silents the type checker.
Writing the correct type is not an easy task, and it is better to leave at the refactoring stage IMO.
transformIgnorePatterns
jest could not understand ESM code.
And by default, the code under node_modules
are not transformed.
To work with packages that are distributed as ESM,
one workaround is to use negative regex match in transformIgnorePatterns so that jest
will actually transpile them.
However, it does not work with all package managers. For example, it doesn't work with monorepo using pnpm. (the example in jest docs only works for simple repo using pnpm)
Therefore, for simplicity, @repobuddy/jest uses jest-esm-transformer-2 to handle that and keep transformIgnorePatterns empty.
About the exports
field
You may wonder why there are:
{
"./presets/ts": {
"types": "./esm/presets/ts/jest-preset.d.ts",
"import": "./esm/presets/ts/jest-preset.js",
"default": "./cjs/presets/ts/jest-preset.js"
},
"./presets/ts/jest-preset": {
"types": "./esm/presets/ts/jest-preset.d.ts",
"import": "./esm/presets/ts/jest-preset.js",
"default": "./cjs/presets/ts/jest-preset.js"
},
}
and /packages/jest/presets/ts
files.
The .../ts
export is needed to export the code and type correctly in TypeScript/JavaScript.
The .../ts/jest-preset
export is need by jest
to work correctly in Linux environment,
and the /packages/jest/presets/ts
is needed to work in Windows environment (or CJS).
🤦