diff --git a/docs/user/config/index.md b/docs/user/config/index.md
index 95d25e165c..b385353a25 100644
--- a/docs/user/config/index.md
+++ b/docs/user/config/index.md
@@ -6,9 +6,19 @@ The later is preferred since it's more customizable, but it depends on your need
## Jest preset
+### The 3 presets
+
+`ts-jest` comes with 3 presets, covering most of project's base configuration:
+
+| Preset name | Description |
+|---|---|
+| `ts-jest/presets/default`
or `ts-jest` | `ts-jest` will take care of `.ts` and `.tsx` files only, leaving JavaScript files as-is. |
+| `ts-jest/presets/js-with-ts` | TypeScript and JavaScript file (`.ts`, `.tsx`, `.js` and `.jsx`) will be handled by `ts-jest`.
You'll need to set `allowJs` to `true` in your `tsconfig.json` file. |
+| `ts-jest/presets/js-with-babel` | TypeScript files will be handled by `ts-jest`, and JavaScript files will be handled by `babel-jest`. |
+
### Basic usage
-In most cases, simply adding `preset: 'ts-jest'` to your Jest config should be enough to start using TypeScript with Jest (assuming you did add `ts-jest` to your dev. dependencies of course):
+In most cases, simply setting the `preset` key to the desired preset name in your Jest config should be enough to start using TypeScript with Jest (assuming you did add `ts-jest` to your dev. dependencies of course):
@@ -16,6 +26,8 @@ In most cases, simply adding `preset: 'ts-jest'` to your Jest config should be e
// jest.config.js
module.exports = {
// [...]
+ // Replace `ts-jest` with the preset you want to use
+ // from the above list
preset: 'ts-jest'
};
```
@@ -27,6 +39,8 @@ module.exports = {
{
// [...]
"jest": {
+ // Replace `ts-jest` with the preset you want to use
+ // from the above list
"preset": "ts-jest"
}
}
@@ -34,20 +48,26 @@ module.exports = {
+**Note:** presets use `testMatch`, like Jest does in its defaults. If you want to use `testRegex` instead in your configuration, you MUST set `testMatch` to `null` or Jest will bail.
+
### Advanced
-The `ts-jest` preset can also be used with other options.
-If you're already using another preset, you might want only some specific settings from the `ts-jest` preset.
+Any preset can also be used with other options.
+If you're already using another preset, you might want only some specific settings from the chosen `ts-jest` preset.
In this case you'll need to use the JavaScript version of Jest config:
```js
// jest.config.js
-const { jestPreset: tsJestPreset } = require('ts-jest');
+const tsJestPresets = require('ts-jest/presets');
+
+const preset = tsJestPresets.defaults
+// const preset = tsJestPresets.jsWithTs
+// const preset = tsJestPresets.jsWithBabel
module.exports = {
// [...]
transform: {
- ...tsJestPreset.transform,
+ ...preset.transform,
// [...]
}
}
diff --git a/e2e/__cases__/allow-js/esm.spec.js b/e2e/__cases__/allow-js/esm.spec.js
new file mode 100644
index 0000000000..4672def549
--- /dev/null
+++ b/e2e/__cases__/allow-js/esm.spec.js
@@ -0,0 +1,5 @@
+import * as bar from './bar'
+
+test('esm', () => {
+ expect(bar).toBe('BAR!')
+})
diff --git a/e2e/__cases__/preset-with-babel/.babelrc b/e2e/__cases__/preset-with-babel/.babelrc
new file mode 100644
index 0000000000..a29ac9986c
--- /dev/null
+++ b/e2e/__cases__/preset-with-babel/.babelrc
@@ -0,0 +1,5 @@
+{
+ "presets": [
+ "@babel/preset-env"
+ ]
+}
diff --git a/e2e/__cases__/preset-with-babel/main.spec.js b/e2e/__cases__/preset-with-babel/main.spec.js
new file mode 100644
index 0000000000..b804480001
--- /dev/null
+++ b/e2e/__cases__/preset-with-babel/main.spec.js
@@ -0,0 +1,3 @@
+test('spread', () => {
+ expect({ ...{ bar: 'foo' }, foo: 'bar' }).toEqual({ foo: 'bar', bar: 'foo' })
+})
diff --git a/e2e/__helpers__/templates.ts b/e2e/__helpers__/templates.ts
index e367b63ef6..d1caae73f6 100644
--- a/e2e/__helpers__/templates.ts
+++ b/e2e/__helpers__/templates.ts
@@ -14,3 +14,9 @@ export const allValidPackageSets = [
PackageSets.jest22,
PackageSets.typescript2_7,
]
+export const allPackageSetsWithPreset = [
+ PackageSets.default,
+ PackageSets.babel6,
+ PackageSets.babel7,
+ PackageSets.typescript2_7,
+]
diff --git a/e2e/__tests__/__snapshots__/allow-js.test.ts.snap b/e2e/__tests__/__snapshots__/allow-js.test.ts.snap
index 33e8f288c0..d5369d6861 100644
--- a/e2e/__tests__/__snapshots__/allow-js.test.ts.snap
+++ b/e2e/__tests__/__snapshots__/allow-js.test.ts.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`Allow JS test should pass using template "default" 1`] = `
+exports[`using babel-jest for js files should pass using template "default" 1`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
@@ -17,7 +17,7 @@ exports[`Allow JS test should pass using template "default" 1`] = `
================================================================================
`;
-exports[`Allow JS test should pass using template "with-babel-6" 1`] = `
+exports[`using babel-jest for js files should pass using template "with-babel-6" 1`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
@@ -34,7 +34,7 @@ exports[`Allow JS test should pass using template "with-babel-6" 1`] = `
================================================================================
`;
-exports[`Allow JS test should pass using template "with-babel-7" 1`] = `
+exports[`using babel-jest for js files should pass using template "with-babel-7" 1`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
@@ -51,7 +51,7 @@ exports[`Allow JS test should pass using template "with-babel-7" 1`] = `
================================================================================
`;
-exports[`Allow JS test should pass using template "with-jest-22" 1`] = `
+exports[`using babel-jest for js files should pass using template "with-jest-22" 1`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
@@ -68,7 +68,7 @@ exports[`Allow JS test should pass using template "with-jest-22" 1`] = `
================================================================================
`;
-exports[`Allow JS test should pass using template "with-typescript-2-7" 1`] = `
+exports[`using babel-jest for js files should pass using template "with-typescript-2-7" 1`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
@@ -84,3 +84,71 @@ exports[`Allow JS test should pass using template "with-typescript-2-7" 1`] = `
Ran all test suites.
================================================================================
`;
+
+exports[`using ts-jest for js files should pass using template "default" 1`] = `
+ √ jest
+ ↳ exit code: 0
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ PASS ./esm.spec.js
+ √ esm
+
+ Test Suites: 1 passed, 1 total
+ Tests: 1 passed, 1 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
+
+exports[`using ts-jest for js files should pass using template "with-babel-6" 1`] = `
+ √ jest
+ ↳ exit code: 0
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ PASS ./esm.spec.js
+ √ esm
+
+ Test Suites: 1 passed, 1 total
+ Tests: 1 passed, 1 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
+
+exports[`using ts-jest for js files should pass using template "with-babel-7" 1`] = `
+ √ jest
+ ↳ exit code: 0
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ PASS ./esm.spec.js
+ √ esm
+
+ Test Suites: 1 passed, 1 total
+ Tests: 1 passed, 1 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
+
+exports[`using ts-jest for js files should pass using template "with-typescript-2-7" 1`] = `
+ √ jest
+ ↳ exit code: 0
+ ===[ STDOUT ]===================================================================
+
+ ===[ STDERR ]===================================================================
+ PASS ./esm.spec.js
+ √ esm
+
+ Test Suites: 1 passed, 1 total
+ Tests: 1 passed, 1 total
+ Snapshots: 0 total
+ Time: XXs
+ Ran all test suites.
+ ================================================================================
+`;
diff --git a/e2e/__tests__/allow-js.test.ts b/e2e/__tests__/allow-js.test.ts
index b3a121b1a8..069aa58552 100644
--- a/e2e/__tests__/allow-js.test.ts
+++ b/e2e/__tests__/allow-js.test.ts
@@ -1,8 +1,10 @@
-import { allValidPackageSets } from '../__helpers__/templates'
+import { allPackageSetsWithPreset, allValidPackageSets } from '../__helpers__/templates'
import { configureTestCase } from '../__helpers__/test-case'
-describe('Allow JS test', () => {
- const testCase = configureTestCase('allow-js')
+describe('using babel-jest for js files', () => {
+ const testCase = configureTestCase('allow-js', {
+ jestConfig: { testMatch: null, testRegex: '(foo|bar)\\.spec\\.[jt]s$' },
+ })
testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => {
it(testLabel, () => {
@@ -12,3 +14,21 @@ describe('Allow JS test', () => {
})
})
})
+
+describe('using ts-jest for js files', () => {
+ const testCase = configureTestCase('allow-js', {
+ jestConfig: {
+ preset: 'ts-jest/presets/js-with-ts',
+ testMatch: null,
+ testRegex: 'esm\\.spec\\.[jt]s$',
+ },
+ })
+
+ testCase.runWithTemplates(allPackageSetsWithPreset, 0, (runTest, { testLabel }) => {
+ it(testLabel, () => {
+ const result = runTest()
+ expect(result.status).toBe(0)
+ expect(result).toMatchSnapshot()
+ })
+ })
+})
diff --git a/e2e/__tests__/jest-presets.test.ts b/e2e/__tests__/jest-presets.test.ts
new file mode 100644
index 0000000000..730c6f0cf7
--- /dev/null
+++ b/e2e/__tests__/jest-presets.test.ts
@@ -0,0 +1,18 @@
+import { allPackageSetsWithPreset } from '../__helpers__/templates'
+import { configureTestCase } from '../__helpers__/test-case'
+
+// 'ts-jest' is tested in almost all test cases
+// 'ts-jest/presets/default' is an alias of the above
+// 'ts-jest/presets/js-with-ts' is tested in allow-js.test.ts
+
+describe('ts-jest/presets/js-with-babel', () => {
+ const testCase = configureTestCase('preset-with-babel', { jestConfig: { preset: 'ts-jest/presets/js-with-babel' } })
+
+ testCase.runWithTemplates(allPackageSetsWithPreset, 1, (runTest, { testLabel }) => {
+ it(testLabel, () => {
+ const result = runTest()
+ expect(result.status).toBe(1)
+ expect(result.stderr).toMatch(/(Couldn't|Cannot) find (preset|module) ["']@babel\/preset-env["']/)
+ })
+ })
+})
diff --git a/jest-preset.js b/jest-preset.js
index a2bdb3e099..54b108e345 100644
--- a/jest-preset.js
+++ b/jest-preset.js
@@ -1,4 +1 @@
-const createJestPreset = require('./dist/config/create-jest-preset')
- .createJestPreset
-
-module.exports = createJestPreset()
+module.exports = require('./presets/default/jest-preset')
diff --git a/presets/create.js b/presets/create.js
new file mode 100644
index 0000000000..50c361c351
--- /dev/null
+++ b/presets/create.js
@@ -0,0 +1 @@
+module.exports = require('../dist/config/create-jest-preset').createJestPreset
diff --git a/presets/default/jest-preset.js b/presets/default/jest-preset.js
new file mode 100644
index 0000000000..bdbaf701a1
--- /dev/null
+++ b/presets/default/jest-preset.js
@@ -0,0 +1 @@
+module.exports = require('..').defaults
diff --git a/presets/index.d.ts b/presets/index.d.ts
new file mode 100644
index 0000000000..2d63d8e167
--- /dev/null
+++ b/presets/index.d.ts
@@ -0,0 +1,5 @@
+import { TsJestPresets } from '../dist/types'
+
+export const defaults: TsJesPresets
+export const jsWithTs: TsJesPresets
+export const jsWithBabel: TsJesPresets
diff --git a/presets/index.js b/presets/index.js
new file mode 100644
index 0000000000..95cca6d7be
--- /dev/null
+++ b/presets/index.js
@@ -0,0 +1,13 @@
+const create = require('./create')
+
+module.exports = {
+ get defaults() { return create() },
+ get jsWithTs() { return create({ allowJs: true }) },
+ get jsWithBabel() {
+ return create({ allowJs: false }, {
+ transform: {
+ '^.+\\.jsx?$': 'babel-jest',
+ },
+ })
+ },
+}
diff --git a/presets/js-with-babel/jest-preset.js b/presets/js-with-babel/jest-preset.js
new file mode 100644
index 0000000000..7e252420ad
--- /dev/null
+++ b/presets/js-with-babel/jest-preset.js
@@ -0,0 +1 @@
+module.exports = require('..').jsWithBabel
diff --git a/presets/js-with-ts/jest-preset.js b/presets/js-with-ts/jest-preset.js
new file mode 100644
index 0000000000..d549de07eb
--- /dev/null
+++ b/presets/js-with-ts/jest-preset.js
@@ -0,0 +1 @@
+module.exports = require('..').jsWithTs
diff --git a/src/cli/cli.spec.ts b/src/cli/cli.spec.ts
index a30adb7412..d555281317 100644
--- a/src/cli/cli.spec.ts
+++ b/src/cli/cli.spec.ts
@@ -1,9 +1,7 @@
-import { testing } from 'bs-logger'
import * as _fs from 'fs'
import { normalize, resolve } from 'path'
-import { mockObject, mockWriteStream, mocked } from '../__helpers__/mocks'
-import { rootLogger as _rootLogger } from '../util/logger'
+import { logTargetMock, mockObject, mockWriteStream, mocked } from '../__helpers__/mocks'
import { processArgv } from '.'
@@ -11,7 +9,7 @@ import { processArgv } from '.'
jest.mock('fs')
const fs = mocked(_fs)
-const rootLogger = _rootLogger as testing.LoggerMock
+const logTarget = logTargetMock()
let lastExitCode: number | undefined
const runCli = async (
@@ -19,7 +17,7 @@ const runCli = async (
): Promise<{ stdout: string; stderr: string; exitCode: number | undefined; log: string }> => {
mockedProcess.stderr.clear()
mockedProcess.stdout.clear()
- rootLogger.target.clear()
+ logTarget.clear()
mockedProcess.argv.splice(2, mockedProcess.argv.length - 2, ...args)
lastExitCode = undefined
await processArgv()
@@ -27,7 +25,7 @@ const runCli = async (
exitCode: lastExitCode,
stdout: mockedProcess.stdout.written.join('\n'),
stderr: mockedProcess.stderr.written.join('\n'),
- log: rootLogger.target.lines.join('\n'),
+ log: logTarget.lines.join('\n'),
}
}
@@ -56,7 +54,7 @@ beforeEach(() => {
fs.writeFileSync.mockClear()
fs.existsSync.mockClear()
fs.readFileSync.mockClear()
- rootLogger.target.clear()
+ logTarget.clear()
})
afterEach(() => {
mockedProcess.mockRestore()
@@ -274,12 +272,19 @@ Options:
describe('migrate', async () => {
const pkgPaths = {
_id: 0,
+ _cfgId: 0,
get next() {
return `./foo/${++pkgPaths._id}/package.json`
},
get current() {
return `./foo/${pkgPaths._id}/package.json`
},
+ get nextCfg() {
+ return `./foo/${pkgPaths._id}/jest.config.${++pkgPaths._cfgId}.js`
+ },
+ get currentCfg() {
+ return `./foo/${pkgPaths._id}/jest.config.${pkgPaths._cfgId}.js`
+ },
}
const noOption = ['config:migrate']
const fullOptions = [...noOption, '--no-jest-preset', '--allow-js']
@@ -315,12 +320,16 @@ Options:
expect(res).toMatchInlineSnapshot(`
Object {
"exitCode": 0,
- "log": "[level:20] creating jest presets not handling JavaScript files
-",
+ "log": "",
"stderr": "
Migrated Jest configuration:
+
+
+Detected preset 'default' as the best matching preset for your configuration.
+Visit https://kulshekhar.github.io/ts-jest/user/config/#jest-preset for more information about presets.
+
",
- "stdout": "{
+ "stdout": "\\"jest\\": {
\\"globals\\": {
\\"ts-jest\\": {
\\"tsConfig\\": {
@@ -350,12 +359,11 @@ Migrated Jest configuration:
expect(res).toMatchInlineSnapshot(`
Object {
"exitCode": 0,
- "log": "[level:20] creating jest presets handling JavaScript files
-",
+ "log": "",
"stderr": "
Migrated Jest configuration:
",
- "stdout": "{
+ "stdout": "\\"jest\\": {
\\"globals\\": {
\\"ts-jest\\": {
\\"tsConfig\\": {
@@ -391,7 +399,7 @@ Migrated Jest configuration:
)
const res = await runCli(...noOption, pkgPaths.current)
expect(res.stdout).toMatchInlineSnapshot(`
-"{
+"\\"jest\\": {
\\"globals\\": {
\\"ts-jest\\": {
\\"tsConfig\\": {
@@ -405,6 +413,95 @@ Migrated Jest configuration:
`)
})
+ it('should reset testMatch if testRegex is used', async () => {
+ expect.assertions(1)
+ fs.existsSync.mockImplementation(() => true)
+ jest.mock(
+ pkgPaths.next,
+ () => ({
+ jest: {
+ testRegex: 'foo-pattern',
+ },
+ }),
+ { virtual: true },
+ )
+ const res = await runCli(...noOption, pkgPaths.current)
+ expect(res.stdout).toMatchInlineSnapshot(`
+"\\"jest\\": {
+ \\"testRegex\\": \\"foo-pattern\\",
+ \\"preset\\": \\"ts-jest\\",
+ \\"testMatch\\": null
+}
+"
+`)
+ })
+
+ it('should detect best preset', async () => {
+ expect.assertions(5)
+ fs.existsSync.mockImplementation(() => true)
+ jest.mock(pkgPaths.next, () => ({}), { virtual: true })
+
+ // defaults
+ jest.doMock(pkgPaths.nextCfg, () => ({}), { virtual: true })
+ let res = await runCli(...noOption, pkgPaths.currentCfg)
+ expect(res.stdout).toMatchInlineSnapshot(`
+"module.exports = {
+ preset: 'ts-jest',
+}
+"
+`)
+
+ // js-with-ts from args
+ jest.doMock(pkgPaths.nextCfg, () => ({}), { virtual: true })
+ res = await runCli(...noOption, '--allow-js', pkgPaths.currentCfg)
+ expect(res.stdout).toMatchInlineSnapshot(`
+"module.exports = {
+ preset: 'ts-jest/presets/js-with-ts',
+}
+"
+`)
+
+ // js-with-ts from previous transform
+ jest.doMock(pkgPaths.nextCfg, () => ({ transform: { '^.+\\.[tj]sx?$': 'ts-jest' } }), { virtual: true })
+ res = await runCli(...noOption, pkgPaths.currentCfg)
+ expect(res.stdout).toMatchInlineSnapshot(`
+"module.exports = {
+ preset: 'ts-jest/presets/js-with-ts',
+}
+"
+`)
+
+ // js-with-babel from previous transform
+ jest.doMock(pkgPaths.nextCfg, () => ({ transform: { '^.+\\.jsx?$': 'babel-jest', '^.+\\.tsx?$': 'ts-jest' } }), {
+ virtual: true,
+ })
+ res = await runCli(...noOption, pkgPaths.currentCfg)
+ expect(res.stdout).toMatchInlineSnapshot(`
+"module.exports = {
+ preset: 'ts-jest/presets/js-with-babel',
+}
+"
+`)
+
+ // defaults when previous transform is ambiguous
+ jest.doMock(
+ pkgPaths.nextCfg,
+ () => ({ transform: { '^src/js/.+\\.jsx?$': 'babel-jest', '^src/ts/.+\\.tsx?$': 'ts-jest' } }),
+ { virtual: true },
+ )
+ res = await runCli(...noOption, pkgPaths.currentCfg)
+ expect(res.stdout).toMatchInlineSnapshot(`
+"module.exports = {
+ transform: {
+ '^src/js/.+\\\\\\\\.jsx?$': 'babel-jest',
+ '^src/ts/.+\\\\\\\\.tsx?$': 'ts-jest',
+ },
+ preset: 'ts-jest',
+}
+"
+`)
+ })
+
it('should normalize transform values', async () => {
expect.assertions(1)
fs.existsSync.mockImplementation(() => true)
@@ -423,7 +520,7 @@ Migrated Jest configuration:
)
const res = await runCli(...noOption, pkgPaths.current)
expect(res.stdout).toMatchInlineSnapshot(`
-"{
+"\\"jest\\": {
\\"transform\\": {
\\"/src/.+\\\\\\\\.[jt]s$\\": \\"ts-jest\\",
\\"foo\\\\\\\\.ts\\": \\"ts-jest\\",
@@ -434,6 +531,7 @@ Migrated Jest configuration:
"
`)
})
+
it('should output help', async () => {
const res = await runCli('help', noOption[0])
expect(res).toMatchInlineSnapshot(`
diff --git a/src/cli/config/migrate.ts b/src/cli/config/migrate.ts
index f03e6d4b85..a4cae6b848 100644
--- a/src/cli/config/migrate.ts
+++ b/src/cli/config/migrate.ts
@@ -6,9 +6,11 @@ import { basename, resolve } from 'path'
import { Arguments } from 'yargs'
import { CliCommand } from '..'
-import { createJestPreset } from '../../config/create-jest-preset'
+import { TsJestPresets } from '../../types'
import { backportJestConfig } from '../../util/backports'
+const DEFAULT_PRESET = 'ts-jest/presets/default'
+
/**
* @internal
*/
@@ -16,6 +18,7 @@ export const run: CliCommand = async (args: Arguments /*, logger: Logger*/) => {
const nullLogger = createLogger({ targets: [] })
const file = args._[0]
const filePath = resolve(process.cwd(), file)
+ const footNotes: string[] = []
if (!existsSync(filePath)) {
throw new Error(`Configuration file ${file} does not exists.`)
}
@@ -33,25 +36,71 @@ export const run: CliCommand = async (args: Arguments /*, logger: Logger*/) => {
// migrate
// first we backport our options
const migratedConfig = backportJestConfig(nullLogger, actualConfig)
+ let presetName: string | undefined
// then we check if we can use `preset`
if (!migratedConfig.preset && args.jestPreset) {
- migratedConfig.preset = 'ts-jest'
- } else if (!args.jestPreset && migratedConfig.preset === 'ts-jest') {
- delete migratedConfig.preset
+ // find the best preset
+ if (args.allowJs) presetName = 'ts-jest/presets/js-with-ts'
+ else {
+ // try to detect what transformer the js extensions would target
+ const jsTransformers = Object.keys(migratedConfig.transform || {}).reduce(
+ (list, pattern) => {
+ if (RegExp(pattern.replace(/^\/?/, '/dummy-project/')).test('/dummy-project/src/foo.js')) {
+ let transformer: string = (migratedConfig.transform as any)[pattern]
+ if (/\bbabel-jest\b/.test(transformer)) transformer = 'babel-jest'
+ else if (/\ts-jest\b/.test(transformer)) transformer = 'ts-jest'
+ return [...list, transformer]
+ }
+ return list
+ },
+ [] as string[],
+ )
+ // depending on the transformer found, we use one or the other preset
+ const jsWithTs = jsTransformers.includes('ts-jest')
+ const jsWithBabel = jsTransformers.includes('babel-jest')
+ if (jsWithBabel && !jsWithTs) {
+ presetName = 'ts-jest/presets/js-with-babel'
+ } else if (jsWithTs && !jsWithBabel) {
+ presetName = 'ts-jest/presets/js-with-ts'
+ } else {
+ // sounds like js files are NOT handled, or handled with a unknown transformer, so we do not need to handle it
+ presetName = DEFAULT_PRESET
+ }
+ }
+ // ensure we are using a preset
+ presetName = presetName || DEFAULT_PRESET
+ migratedConfig.preset = presetName
+ footNotes.push(
+ `Detected preset '${presetName.replace(
+ /^ts-jest\/presets\//,
+ '',
+ )}' as the best matching preset for your configuration.\nVisit https://kulshekhar.github.io/ts-jest/user/config/#jest-preset for more information about presets.\n`,
+ )
+ } else if (migratedConfig.preset && migratedConfig.preset.startsWith('ts-jest')) {
+ if (args.jestPreset === false) {
+ delete migratedConfig.preset
+ } else {
+ presetName = migratedConfig.preset
+ }
}
- const usesPreset = migratedConfig.preset === 'ts-jest'
- const presets = createJestPreset({ allowJs: args.allowJs })
+ const presets: TsJestPresets | undefined = presetName
+ ? require(`../../../${presetName.replace(/^ts-jest\//, '')}/jest-preset`)
+ : undefined
// check the extensions
- if (migratedConfig.moduleFileExtensions && migratedConfig.moduleFileExtensions.length && usesPreset) {
+ if (migratedConfig.moduleFileExtensions && migratedConfig.moduleFileExtensions.length && presets) {
const presetValue = dedupSort(presets.moduleFileExtensions).join('::')
const migratedValue = dedupSort(migratedConfig.moduleFileExtensions).join('::')
if (presetValue === migratedValue) {
delete migratedConfig.moduleFileExtensions
}
}
+ // there is a testRegex, remove our testMatch
+ if (migratedConfig.testRegex && presets) {
+ migratedConfig.testMatch = null as any
+ }
// check the testMatch
- if (migratedConfig.testMatch && migratedConfig.testMatch.length && usesPreset) {
+ else if (migratedConfig.testMatch && migratedConfig.testMatch.length && presets) {
const presetValue = dedupSort(presets.testMatch).join('::')
const migratedValue = dedupSort(migratedConfig.testMatch).join('::')
if (presetValue === migratedValue) {
@@ -71,7 +120,7 @@ export const run: CliCommand = async (args: Arguments /*, logger: Logger*/) => {
}
// check if it's the same as the preset's one
if (
- usesPreset &&
+ presets &&
migratedConfig.transform &&
stringifyJson(migratedConfig.transform) === stringifyJson(presets.transform)
) {
@@ -91,7 +140,7 @@ No migration needed for given Jest configuration
}
const stringify = /\.json$/.test(file) ? JSON.stringify : stringifyJson5
- const footNotes: string[] = []
+ const prefix = /\.json$/.test(file) ? '"jest": ' : 'module.exports = '
// if we are using preset, inform the user that he might be able to remove some section(s)
// we couldn't check for equality
@@ -105,7 +154,7 @@ No migration needed for given Jest configuration
// If it is the case, you can safely remove the "testMatch" from what I've migrated.
// `)
// }
- if (usesPreset && migratedConfig.transform) {
+ if (presets && migratedConfig.transform) {
footNotes.push(`
I couldn't check if your "transform" value is the same as mine which is: ${stringify(
presets.transform,
@@ -120,7 +169,7 @@ If it is the case, you can safely remove the "transform" from what I've migrated
process.stderr.write(`
Migrated Jest configuration:
`)
- process.stdout.write(`${stringify(migratedConfig, undefined, ' ')}\n`)
+ process.stdout.write(`${prefix}${stringify(migratedConfig, undefined, ' ')}\n`)
if (footNotes.length) {
process.stderr.write(`
${footNotes.join('\n')}
@@ -148,6 +197,7 @@ function cleanupConfig(config: jest.InitialOptions): void {
config.testMatch = dedupSort(config.testMatch)
if (config.testMatch.length === 0) delete config.testMatch
}
+ if (config.preset === DEFAULT_PRESET) config.preset = 'ts-jest'
}
function dedupSort(arr: any[]) {
diff --git a/src/config/create-jest-preset.spec.ts b/src/config/create-jest-preset.spec.ts
index 82bc1f3a5f..75e06a6aea 100644
--- a/src/config/create-jest-preset.spec.ts
+++ b/src/config/create-jest-preset.spec.ts
@@ -31,3 +31,46 @@ it('should return correct defaults when allowJs is true', () => {
},
})
})
+
+it('should be able to use a base config', () => {
+ expect(createJestPreset(undefined, {})).toMatchInlineSnapshot(`
+Object {
+ "moduleFileExtensions": Array [
+ "js",
+ "json",
+ "jsx",
+ "node",
+ "ts",
+ "tsx",
+ ],
+ "testMatch": Array [
+ "**/__tests__/**/*.js?(x)",
+ "**/?(*.)+(spec|test).js?(x)",
+ "**/__tests__/**/*.ts?(x)",
+ "**/?(*.)+(spec|test).ts?(x)",
+ ],
+ "transform": Object {
+ "^.+\\\\.tsx?$": "ts-jest",
+ },
+}
+`)
+ expect(createJestPreset(undefined, { testMatch: ['foo'], moduleFileExtensions: ['bar'], transform: { foo: 'bar' } }))
+ .toMatchInlineSnapshot(`
+Object {
+ "moduleFileExtensions": Array [
+ "bar",
+ "ts",
+ "tsx",
+ ],
+ "testMatch": Array [
+ "foo",
+ "**/__tests__/**/*.ts?(x)",
+ "**/?(*.)+(spec|test).ts?(x)",
+ ],
+ "transform": Object {
+ "^.+\\\\.tsx?$": "ts-jest",
+ "foo": "bar",
+ },
+}
+`)
+})
diff --git a/src/config/create-jest-preset.ts b/src/config/create-jest-preset.ts
index 07a2976ab0..999c500c20 100644
--- a/src/config/create-jest-preset.ts
+++ b/src/config/create-jest-preset.ts
@@ -1,6 +1,6 @@
import * as jestConfig from 'jest-config'
-import { CreateJestPresetOptions } from '../types'
+import { CreateJestPresetOptions, TsJestPresets } from '../types'
import { rootLogger } from '../util/logger'
const logger = rootLogger.child({ namespace: 'jest-preset' })
@@ -14,16 +14,17 @@ const defaults = jestConfig.defaults || {
export function createJestPreset(
{ allowJs = false }: CreateJestPresetOptions = {},
- from: jest.InitialOptions = defaults,
-) {
+ from?: jest.InitialOptions,
+): TsJestPresets {
logger.debug({ allowJs }, 'creating jest presets', allowJs ? 'handling' : 'not handling', 'JavaScript files')
+ from = { ...defaults, ...from }
return {
transform: {
...from.transform,
[allowJs ? '^.+\\.[tj]sx?$' : '^.+\\.tsx?$']: 'ts-jest',
},
- testMatch: dedup([...from.testMatch, '**/__tests__/**/*.ts?(x)', '**/?(*.)+(spec|test).ts?(x)']),
- moduleFileExtensions: dedup([...from.moduleFileExtensions, 'ts', 'tsx']),
+ testMatch: dedup([...(from.testMatch || []), '**/__tests__/**/*.ts?(x)', '**/?(*.)+(spec|test).ts?(x)']),
+ moduleFileExtensions: dedup([...(from.moduleFileExtensions || []), 'ts', 'tsx']),
}
}
diff --git a/src/types.ts b/src/types.ts
index 7e9b84081a..6feff23c1c 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -69,6 +69,12 @@ export interface TsJestGlobalOptions {
stringifyContentPathRegex?: string | RegExp
}
+export interface TsJestPresets {
+ transform: Record
+ testMatch: string[]
+ moduleFileExtensions: string[]
+}
+
interface TsJestConfig$tsConfig$file {
kind: 'file'
value: string | undefined