diff --git a/.travis.yml b/.travis.yml index 40686a9023..28f52590e6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: node_js env: - - TS_JEST_E2E_WORKDIR=/tmp/ts-jest-e2e-workdir + - TS_JEST_E2E_WORKDIR=/tmp/ts-jest-e2e-workdir TS_JEST_E2E_OPTIMIZATIONS=1 cache: npm: true diff --git a/appveyor.yml b/appveyor.yml index 7610f4e0f9..0aaae05f7e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,6 +24,7 @@ install: # - set CI=true # Our E2E work dir - set TS_JEST_E2E_WORKDIR=%APPDATA%\ts-jest-e2e + - set TS_JEST_E2E_OPTIMIZATIONS=1 - npm ci --ignore-scripts - npm run clean -- --when-ci-commit-message diff --git a/e2e/__cases__/module-kinds/import-default.spec.ts b/e2e/__cases__/module-kinds/import-default.spec.ts new file mode 100644 index 0000000000..5dbf7d7589 --- /dev/null +++ b/e2e/__cases__/module-kinds/import-default.spec.ts @@ -0,0 +1,7 @@ +import lib from './lib' + +test('import default', () => { + expect(typeof lib).toBe('function') + expect(lib()).toBe('foo') + expect(lib.bar).toBe('bar') +}) diff --git a/e2e/__cases__/module-kinds/import-legacy.spec.ts b/e2e/__cases__/module-kinds/import-legacy.spec.ts new file mode 100644 index 0000000000..1430b2ca3f --- /dev/null +++ b/e2e/__cases__/module-kinds/import-legacy.spec.ts @@ -0,0 +1,7 @@ +import lib = require('./lib') + +test('import default', () => { + expect(typeof lib).toBe('function') + expect(lib()).toBe('foo') + expect(lib.bar).toBe('bar') +}) diff --git a/e2e/__cases__/module-kinds/import-star.spec.ts b/e2e/__cases__/module-kinds/import-star.spec.ts new file mode 100644 index 0000000000..3f94ebce9d --- /dev/null +++ b/e2e/__cases__/module-kinds/import-star.spec.ts @@ -0,0 +1,7 @@ +import * as lib from './lib' + +test('import default', () => { + expect(typeof lib).toBe('function') + expect(lib()).toBe('foo') + expect(lib.bar).toBe('bar') +}) diff --git a/e2e/__cases__/module-kinds/lib.d.ts b/e2e/__cases__/module-kinds/lib.d.ts new file mode 100644 index 0000000000..9759f33701 --- /dev/null +++ b/e2e/__cases__/module-kinds/lib.d.ts @@ -0,0 +1,5 @@ +declare function lib () +declare namespace lib { + export const bar: string +} +export = lib diff --git a/e2e/__cases__/module-kinds/lib.js b/e2e/__cases__/module-kinds/lib.js new file mode 100644 index 0000000000..71e3ad5646 --- /dev/null +++ b/e2e/__cases__/module-kinds/lib.js @@ -0,0 +1,5 @@ +function lib() { return 'foo' } + +lib.bar = 'bar' + +module.exports = lib diff --git a/e2e/__cases__/module-kinds/tsconfig.json b/e2e/__cases__/module-kinds/tsconfig.json new file mode 100644 index 0000000000..46b77f8c17 --- /dev/null +++ b/e2e/__cases__/module-kinds/tsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "allowJs": true, + "rootDir": ".", + "outDir": "dist" + } +} diff --git a/e2e/__helpers__/test-case/__hooks-source__.js.hbs b/e2e/__helpers__/test-case/__hooks-source__.js.hbs index 286ef5fc94..25e8c3af12 100644 --- a/e2e/__helpers__/test-case/__hooks-source__.js.hbs +++ b/e2e/__helpers__/test-case/__hooks-source__.js.hbs @@ -3,13 +3,13 @@ const fs = require('fs') const path = require('path') const root = __dirname -const writeProcessIoTo = {{writeProcessIoTo}} +const writeProcessIoTo = path.resolve(root, {{writeProcessIoTo}}) exports.afterProcess = function (args, result) { // const source = args[0] const filePath = args[1] const relPath = path.relative(root, filePath) - if (writeProcessIoTo && filePath.startsWith(`${root}${path.sep}`)) { + if (filePath.startsWith(`${root}${path.sep}`)) { const dest = `${path.join(writeProcessIoTo, relPath)}.json` const segments = relPath.split(path.sep) segments.pop() diff --git a/e2e/__helpers__/test-case/run-descriptor.ts b/e2e/__helpers__/test-case/run-descriptor.ts index 8c40e86e32..c76e0a7cea 100644 --- a/e2e/__helpers__/test-case/run-descriptor.ts +++ b/e2e/__helpers__/test-case/run-descriptor.ts @@ -26,7 +26,10 @@ export default class RunDescriptor { } get sourcePackageJson() { - return this._sourcePackageJson || (this._sourcePackageJson = require(join(this.sourceDir, 'package.json'))) + try { + return this._sourcePackageJson || (this._sourcePackageJson = require(join(this.sourceDir, 'package.json'))) + } catch (err) {} + return {} } get templateName(): string { @@ -45,8 +48,18 @@ export default class RunDescriptor { if (logUnlessStatus != null && logUnlessStatus !== result.status) { // tslint:disable-next-line:no-console console.log( - `Output of test run in "${this.name}" using template "${this.templateName}" (exit code: ${result.status}):\n\n`, + '='.repeat(70), + '\n', + `Test exited with unexpected status in "${this.name}" using template "${this.templateName}" (exit code: ${ + result.status + }):\n`, + result.context.cmd, + result.context.args.join(' '), + '\n\n', result.output.trim(), + '\n', + '='.repeat(70), + '\n', ) } return result diff --git a/e2e/__helpers__/test-case/run-result.ts b/e2e/__helpers__/test-case/run-result.ts index ca80a640e5..a8202c30b8 100644 --- a/e2e/__helpers__/test-case/run-result.ts +++ b/e2e/__helpers__/test-case/run-result.ts @@ -20,6 +20,7 @@ export default class RunResult { args: string[] env: { [key: string]: string } config: jest.InitialOptions + digest: string }>, ) {} get logFilePath() { @@ -44,26 +45,29 @@ export default class RunResult { return this.result.status } get output() { - return stripAnsiColors(this.result.output ? this.result.output.join('\n\n') : '') + return this.normalize(stripAnsiColors(this.result.output ? this.result.output.join('\n\n') : '')) } get stderr() { - return stripAnsiColors((this.result.stderr || '').toString()) + return this.normalize(stripAnsiColors((this.result.stderr || '').toString())) } get normalizedStderr() { return normalizeJestOutput(this.stderr) } get stdout() { - return stripAnsiColors((this.result.stdout || '').toString()) + return this.normalize(stripAnsiColors((this.result.stdout || '').toString())) } get normalizedStdout() { return normalizeJestOutput(this.stdout) } get cmdLine() { - return this.normalize( - [this.context.cmd, ...this.context.args] - .filter(a => !['-u', '--updateSnapshot', '--runInBand', '--'].includes(a)) - .join(' '), + const args = [this.context.cmd, ...this.context.args].filter( + a => !['-u', '--updateSnapshot', '--runInBand', '--'].includes(a), ) + const configIndex = args.indexOf('--config') + if (configIndex !== -1) { + args.splice(configIndex, 2) + } + return this.normalize(args.join(' ')) } ioFor(relFilePath: string): ProcessedFileIo { diff --git a/e2e/__helpers__/test-case/runtime.ts b/e2e/__helpers__/test-case/runtime.ts index c4eb2b5684..41a542f037 100644 --- a/e2e/__helpers__/test-case/runtime.ts +++ b/e2e/__helpers__/test-case/runtime.ts @@ -1,4 +1,6 @@ import { sync as spawnSync } from 'cross-spawn' +import { createHash } from 'crypto' +import stringifyJson from 'fast-json-stable-stringify' import { copySync, ensureSymlinkSync, @@ -11,10 +13,12 @@ import { readdirSync, realpathSync, removeSync, + renameSync, statSync, symlinkSync, writeFileSync, } from 'fs-extra' +import { stringify as stringifyJson5 } from 'json5' import merge from 'lodash.merge' import { join, relative, resolve, sep } from 'path' @@ -22,7 +26,7 @@ import * as Paths from '../../../scripts/lib/paths' import RunResult from './run-result' import { PreparedTest, RunTestOptions } from './types' -import { templateNameForPath } from './utils' +import { enableOptimizations, templateNameForPath } from './utils' const TEMPLATE_EXCLUDED_ITEMS = ['node_modules', 'package-lock.json'] @@ -49,25 +53,18 @@ function hooksSourceWith(vars: Record): string { } export function run(name: string, options: RunTestOptions = {}): RunResult { - const { - args = [], - env = {}, - template, - inject, - writeIo, - noCache, - jestConfigPath: configFile = 'jest.config.js', - } = options - const { workdir: dir, sourceDir, hooksFile, ioDir } = prepareTest( + const { env = {}, template, inject, writeIo, noCache, jestConfigPath: configFile = 'jest.config.js' } = options + const { workdir: dir, sourceDir } = prepareTest( name, template || templateNameForPath(join(Paths.e2eSourceDir, name)), options, ) const pkg = readJsonSync(join(dir, 'package.json')) + const jestConfigPath = (path: string = dir) => resolve(path, configFile) + // grab base configuration - const jestConfigPath = resolve(dir, configFile) - let baseConfig: jest.InitialOptions = require(jestConfigPath) + let baseConfig: jest.InitialOptions = require(jestConfigPath()) if (configFile === 'package.json') baseConfig = (baseConfig as any).jest const extraConfig = {} as jest.InitialOptions @@ -81,25 +78,14 @@ export function run(name: string, options: RunTestOptions = {}): RunResult { if (process.argv.find(v => ['--updateSnapshot', '-u'].includes(v))) { cmdArgs.push('-u') } - cmdArgs.push(...args) if (!inject && pkg.scripts && pkg.scripts.test) { - if (cmdArgs.length) { - cmdArgs.unshift('--') - } - cmdArgs = ['npm', '-s', 'run', 'test', ...cmdArgs] + cmdArgs = ['npm', '-s', 'run', 'test', '--', ...cmdArgs] shortCmd = 'npm' } else { - cmdArgs.unshift(join(dir, 'node_modules', '.bin', 'jest')) + cmdArgs.unshift(join('node_modules', '.bin', 'jest')) shortCmd = 'jest' } - // check/merge config - if (cmdArgs.includes('--config')) { - throw new Error(`Extend config using tsJestConfig and jestConfig options, not thru args.`) - } - if (cmdArgs.includes('--no-cache')) { - throw new Error(`Use the noCache option to disable cache, not thru args.`) - } // extends config if (options.jestConfig) { merge(extraConfig, options.jestConfig) @@ -110,21 +96,39 @@ export function run(name: string, options: RunTestOptions = {}): RunResult { merge(tsJestConfig, options.tsJestConfig) } + // cache dir if (noCache || writeIo) { cmdArgs.push('--no-cache') + extraConfig.cacheDirectory = undefined } else if (!(baseConfig.cacheDirectory || extraConfig.cacheDirectory)) { // force the cache directory if not set extraConfig.cacheDirectory = join(Paths.cacheDir, `e2e-${template}`) } - // write final config + // build final config and create dir suffix based on it const finalConfig = merge({}, baseConfig, extraConfig) - if (Object.keys(extraConfig).length !== 0) { + const digest = createHash('sha1') + .update(stringifyJson(finalConfig)) + .digest('hex') + // this must be in the same path hierarchy as dir + const nextDirPrefix = `${dir}-${digest.substr(0, 7)}.` + let index = 1 + while (existsSync(`${nextDirPrefix}${index}`)) index++ + const nextDir = `${nextDirPrefix}${index}` + + // move the directory related to config digest + renameSync(dir, nextDir) + + // write final config + // FIXME: sounds like the json fail to be encoded as an arg + if (false /* enableOptimizations() */) { + cmdArgs.push('--config', JSON.stringify(finalConfig)) + } else if (Object.keys(extraConfig).length !== 0) { if (configFile === 'package.json') { pkg.jest = finalConfig - outputJsonSync(jestConfigPath, pkg) + outputJsonSync(jestConfigPath(nextDir), pkg) } else { - outputFileSync(jestConfigPath, `module.exports = ${JSON.stringify(finalConfig, null, 2)}`, 'utf8') + outputFileSync(jestConfigPath(nextDir), `module.exports = ${JSON.stringify(finalConfig, null, 2)}`, 'utf8') } } @@ -134,48 +138,74 @@ export function run(name: string, options: RunTestOptions = {}): RunResult { } const cmd = cmdArgs.shift() as string + if (cmdArgs[cmdArgs.length - 1] === '--') cmdArgs.pop() - // Add both process.env which is the standard and custom env variables - const mergedEnv: any = { - ...process.env, - ...env, - } + // extend env + const localEnv: any = { ...env } if (inject) { const injected = typeof inject === 'function' ? `(${inject.toString()}).apply(this);` : inject - mergedEnv.__TS_JEST_EVAL = injected + localEnv.__TS_JEST_EVAL = injected } if (writeIo) { - mergedEnv.TS_JEST_HOOKS = hooksFile + localEnv.TS_JEST_HOOKS = defaultHooksFile('.') } - const result = spawnSync(cmd, cmdArgs, { - cwd: dir, - env: mergedEnv, - }) + // arguments to give to spawn + const spawnOptions: { env: Record; cwd: string } = { env: localEnv } as any + + // create started script for debugging + if (!enableOptimizations()) { + outputFileSync( + join(nextDir, '__launch.js'), + ` +const { execFile } = require('child_process') +const cmd = ${stringifyJson5(cmd, null, 2)} +const args = ${stringifyJson5(cmdArgs, null, 2)} +const options = ${stringifyJson5(spawnOptions, null, 2)} +options.env = Object.assign({}, process.env, options.env) +execFile(cmd, args, options) +`, + 'utf8', + ) + } + + // extend env with our env + spawnOptions.env = { ...process.env, ...localEnv } + spawnOptions.cwd = nextDir + + // run jest + const result = spawnSync(cmd, cmdArgs, spawnOptions) // we need to copy each snapshot which does NOT exists in the source dir - readdirSync(dir).forEach(item => { - if (item === 'node_modules' || !statSync(join(dir, item)).isDirectory()) { - return - } - const srcDir = join(sourceDir, item) - const wrkDir = join(dir, item) - copySync(wrkDir, srcDir, { - overwrite: false, - filter: from => { - return relative(sourceDir, from) - .split(sep) - .includes('__snapshots__') - }, + if (!enableOptimizations()) { + readdirSync(nextDir).forEach(item => { + if (item === 'node_modules' || !statSync(join(nextDir, item)).isDirectory()) { + return + } + const srcDir = join(sourceDir, item) + const wrkDir = join(nextDir, item) + + // do not try to copy a linked root snapshots + if (item === '__snapshots__' && existsSync(srcDir)) return + + copySync(wrkDir, srcDir, { + overwrite: false, + filter: from => { + return relative(sourceDir, from) + .split(sep) + .includes('__snapshots__') + }, + }) }) - }) + } - return new RunResult(realpathSync(dir), result, { + return new RunResult(realpathSync(nextDir), result, { cmd: shortCmd, args: cmdArgs, - env: mergedEnv, - ioDir: writeIo ? ioDir : undefined, + env: localEnv, + ioDir: writeIo ? ioDirForPath(nextDir) : undefined, config: finalConfig, + digest, }) } @@ -247,18 +277,19 @@ export function prepareTest(name: string, template: string, options: RunTestOpti // create the special files outputFileSync(join(caseWorkdir, '__eval.ts'), EVAL_SOURCE, 'utf8') let ioDir!: string + // hooks if (options.writeIo) { - ioDir = join(caseWorkdir, '__io__') + ioDir = ioDirForPath(caseWorkdir) mkdirpSync(ioDir) + const hooksFile = defaultHooksFile(caseWorkdir) + outputFileSync( + hooksFile, + hooksSourceWith({ + writeProcessIoTo: ioDirForPath('.') || false, + }), + 'utf8', + ) } - const hooksFile = join(caseWorkdir, '__hooks.js') - outputFileSync( - hooksFile, - hooksSourceWith({ - writeProcessIoTo: ioDir || false, - }), - 'utf8', - ) // create a package.json if it does not exists, and/or enforce the package name const pkgFile = join(caseWorkdir, 'package.json') @@ -268,5 +299,13 @@ export function prepareTest(name: string, template: string, options: RunTestOpti pkg.version = `0.0.0-mock0` outputJsonSync(pkgFile, pkg, { spaces: 2 }) - return { workdir: caseWorkdir, templateDir, sourceDir, hooksFile, ioDir } + return { workdir: caseWorkdir, templateDir, sourceDir } +} + +function ioDirForPath(path: string) { + return join(path, '__io__') +} + +function defaultHooksFile(path: string) { + return join(path, '__hooks.js') } diff --git a/e2e/__helpers__/test-case/types.ts b/e2e/__helpers__/test-case/types.ts index 3df848b707..459ada4fe5 100644 --- a/e2e/__helpers__/test-case/types.ts +++ b/e2e/__helpers__/test-case/types.ts @@ -5,7 +5,6 @@ import RunResult from './run-result' export interface RunTestOptions { template?: string env?: {} - args?: string[] inject?: (() => any) | string writeIo?: boolean jestConfig?: jest.ProjectConfig | any @@ -30,6 +29,4 @@ export interface PreparedTest { workdir: string templateDir: string sourceDir: string - ioDir: string - hooksFile: string } diff --git a/e2e/__helpers__/test-case/utils.ts b/e2e/__helpers__/test-case/utils.ts index 5a6b446edd..2a87c9160b 100644 --- a/e2e/__helpers__/test-case/utils.ts +++ b/e2e/__helpers__/test-case/utils.ts @@ -47,3 +47,7 @@ export function normalizeJestOutput(output: string): string { export function escapeRegex(s: string) { return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') } + +export function enableOptimizations() { + return !!process.env.TS_JEST_E2E_OPTIMIZATIONS +} diff --git a/e2e/__tests__/__snapshots__/coverage.test.ts.snap b/e2e/__tests__/__snapshots__/coverage.test.ts.snap index dbb6679cc7..4dc8a2504f 100644 --- a/e2e/__tests__/__snapshots__/coverage.test.ts.snap +++ b/e2e/__tests__/__snapshots__/coverage.test.ts.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`using template "default" should report coverages 1`] = ` - √ jest --coverage + √ jest ↳ exit code: 0 ===[ STDOUT ]=================================================================== ----------|----------|----------|----------|----------|-------------------| @@ -24,7 +24,7 @@ exports[`using template "default" should report coverages 1`] = ` `; exports[`using template "with-babel-6" should report coverages 1`] = ` - √ jest --coverage + √ jest ↳ exit code: 0 ===[ STDOUT ]=================================================================== ----------|----------|----------|----------|----------|-------------------| @@ -47,7 +47,7 @@ exports[`using template "with-babel-6" should report coverages 1`] = ` `; exports[`using template "with-babel-7" should report coverages 1`] = ` - √ jest --coverage + √ jest ↳ exit code: 0 ===[ STDOUT ]=================================================================== ----------|----------|----------|----------|----------|-------------------| @@ -70,7 +70,7 @@ exports[`using template "with-babel-7" should report coverages 1`] = ` `; exports[`using template "with-jest-22" should report coverages 1`] = ` - √ jest --coverage + √ jest ↳ exit code: 0 ===[ STDOUT ]=================================================================== ----------|----------|----------|----------|----------|-------------------| @@ -93,7 +93,7 @@ exports[`using template "with-jest-22" should report coverages 1`] = ` `; exports[`using template "with-typescript-2-7" should report coverages 1`] = ` - √ jest --coverage + √ jest ↳ exit code: 0 ===[ STDOUT ]=================================================================== ----------|----------|----------|----------|----------|-------------------| diff --git a/e2e/__tests__/coverage.test.ts b/e2e/__tests__/coverage.test.ts index 423595d33d..97b94bcbd5 100644 --- a/e2e/__tests__/coverage.test.ts +++ b/e2e/__tests__/coverage.test.ts @@ -2,7 +2,7 @@ import { allValidPackageSets } from '../__helpers__/templates' import { configureTestCase } from '../__helpers__/test-case' const testCase = configureTestCase('simple', { - args: ['--coverage'], + jestConfig: { collectCoverage: true }, }) testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { templateName }) => { diff --git a/e2e/__tests__/module-kinds/__snapshots__/amd.test.ts.snap b/e2e/__tests__/module-kinds/__snapshots__/amd.test.ts.snap new file mode 100644 index 0000000000..cd83e1b814 --- /dev/null +++ b/e2e/__tests__/module-kinds/__snapshots__/amd.test.ts.snap @@ -0,0 +1,157 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`run with options: {"module":"amd","allowSyntheticDefaultImports":false} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + message TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-default.spec.ts:1:8 - error TS1192: Module '"/lib"' has no default export. + + 1 import lib from './lib' + ~~~ + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"amd","allowSyntheticDefaultImports":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"amd","esModuleInterop":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-star.spec.ts:5:10 - error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof lib' has no compatible call signatures. + + 5 expect(lib()).toBe('foo') + ~~~~~ + + import-star.spec.ts:1:1 + 1 import * as lib from './lib' + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Type originates at this import. A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Consider using a default import or import require here instead. + FAIL ./import-star.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "object" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-star.spec.ts:4:22) + + PASS ./import-default.spec.ts + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"amd"} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + message TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; diff --git a/e2e/__tests__/module-kinds/__snapshots__/commonjs.test.ts.snap b/e2e/__tests__/module-kinds/__snapshots__/commonjs.test.ts.snap new file mode 100644 index 0000000000..91fe0d68f8 --- /dev/null +++ b/e2e/__tests__/module-kinds/__snapshots__/commonjs.test.ts.snap @@ -0,0 +1,158 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`run with options: {"module":"commonjs","allowSyntheticDefaultImports":false} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-default.spec.ts:1:8 - error TS1192: Module '"/lib"' has no default export. + + 1 import lib from './lib' + ~~~ + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"commonjs","allowSyntheticDefaultImports":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"commonjs","esModuleInterop":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-star.spec.ts:5:10 - error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof lib' has no compatible call signatures. + + 5 expect(lib()).toBe('foo') + ~~~~~ + + import-star.spec.ts:1:1 + 1 import * as lib from './lib' + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Type originates at this import. A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Consider using a default import or import require here instead. + FAIL ./import-star.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "object" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-star.spec.ts:4:22) + + PASS ./import-default.spec.ts + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"commonjs"} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-default.spec.ts:1:8 - error TS1192: Module '"/lib"' has no default export. + + 1 import lib from './lib' + ~~~ + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; diff --git a/e2e/__tests__/module-kinds/__snapshots__/es2015.test.ts.snap b/e2e/__tests__/module-kinds/__snapshots__/es2015.test.ts.snap new file mode 100644 index 0000000000..f66be25b8c --- /dev/null +++ b/e2e/__tests__/module-kinds/__snapshots__/es2015.test.ts.snap @@ -0,0 +1,157 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`run with options: {"module":"es2015","allowSyntheticDefaultImports":false} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + message TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-default.spec.ts:1:8 - error TS1192: Module '"/lib"' has no default export. + + 1 import lib from './lib' + ~~~ + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"es2015","allowSyntheticDefaultImports":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"es2015","esModuleInterop":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-star.spec.ts:5:10 - error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof lib' has no compatible call signatures. + + 5 expect(lib()).toBe('foo') + ~~~~~ + + import-star.spec.ts:1:1 + 1 import * as lib from './lib' + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Type originates at this import. A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Consider using a default import or import require here instead. + FAIL ./import-star.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "object" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-star.spec.ts:4:22) + + PASS ./import-default.spec.ts + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"es2015"} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + message TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; diff --git a/e2e/__tests__/module-kinds/__snapshots__/esnext.test.ts.snap b/e2e/__tests__/module-kinds/__snapshots__/esnext.test.ts.snap new file mode 100644 index 0000000000..12ff1baa83 --- /dev/null +++ b/e2e/__tests__/module-kinds/__snapshots__/esnext.test.ts.snap @@ -0,0 +1,157 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`run with options: {"module":"esnext","allowSyntheticDefaultImports":false} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + message TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-default.spec.ts:1:8 - error TS1192: Module '"/lib"' has no default export. + + 1 import lib from './lib' + ~~~ + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"esnext","allowSyntheticDefaultImports":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"esnext","esModuleInterop":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-star.spec.ts:5:10 - error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof lib' has no compatible call signatures. + + 5 expect(lib()).toBe('foo') + ~~~~~ + + import-star.spec.ts:1:1 + 1 import * as lib from './lib' + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Type originates at this import. A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Consider using a default import or import require here instead. + FAIL ./import-star.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "object" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-star.spec.ts:4:22) + + PASS ./import-default.spec.ts + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"esnext"} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + message TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; diff --git a/e2e/__tests__/module-kinds/__snapshots__/none.test.ts.snap b/e2e/__tests__/module-kinds/__snapshots__/none.test.ts.snap new file mode 100644 index 0000000000..72ad8bdbe7 --- /dev/null +++ b/e2e/__tests__/module-kinds/__snapshots__/none.test.ts.snap @@ -0,0 +1,157 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`run with options: {"module":"none","allowSyntheticDefaultImports":false} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + message TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-default.spec.ts:1:8 - error TS1192: Module '"/lib"' has no default export. + + 1 import lib from './lib' + ~~~ + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"none","allowSyntheticDefaultImports":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"none","esModuleInterop":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-star.spec.ts:5:10 - error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof lib' has no compatible call signatures. + + 5 expect(lib()).toBe('foo') + ~~~~~ + + import-star.spec.ts:1:1 + 1 import * as lib from './lib' + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Type originates at this import. A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Consider using a default import or import require here instead. + FAIL ./import-star.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "object" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-star.spec.ts:4:22) + + PASS ./import-default.spec.ts + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"none"} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + message TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; diff --git a/e2e/__tests__/module-kinds/__snapshots__/system.test.ts.snap b/e2e/__tests__/module-kinds/__snapshots__/system.test.ts.snap new file mode 100644 index 0000000000..95ad42002e --- /dev/null +++ b/e2e/__tests__/module-kinds/__snapshots__/system.test.ts.snap @@ -0,0 +1,157 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`run with options: {"module":"system","allowSyntheticDefaultImports":false} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + message TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-default.spec.ts:1:8 - error TS1192: Module '"/lib"' has no default export. + + 1 import lib from './lib' + ~~~ + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"system","allowSyntheticDefaultImports":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"system","esModuleInterop":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-star.spec.ts:5:10 - error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof lib' has no compatible call signatures. + + 5 expect(lib()).toBe('foo') + ~~~~~ + + import-star.spec.ts:1:1 + 1 import * as lib from './lib' + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Type originates at this import. A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Consider using a default import or import require here instead. + FAIL ./import-star.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "object" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-star.spec.ts:4:22) + + PASS ./import-default.spec.ts + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"system"} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + message TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; diff --git a/e2e/__tests__/module-kinds/__snapshots__/umd.test.ts.snap b/e2e/__tests__/module-kinds/__snapshots__/umd.test.ts.snap new file mode 100644 index 0000000000..65f7999bbc --- /dev/null +++ b/e2e/__tests__/module-kinds/__snapshots__/umd.test.ts.snap @@ -0,0 +1,157 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`run with options: {"module":"umd","allowSyntheticDefaultImports":false} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + message TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-default.spec.ts:1:8 - error TS1192: Module '"/lib"' has no default export. + + 1 import lib from './lib' + ~~~ + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"umd","allowSyntheticDefaultImports":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"umd","esModuleInterop":true} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./import-legacy.spec.ts + ts-jest[ts-compiler] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + import-star.spec.ts:5:10 - error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'typeof lib' has no compatible call signatures. + + 5 expect(lib()).toBe('foo') + ~~~~~ + + import-star.spec.ts:1:1 + 1 import * as lib from './lib' + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Type originates at this import. A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Consider using a default import or import require here instead. + FAIL ./import-star.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "object" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-star.spec.ts:4:22) + + PASS ./import-default.spec.ts + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; + +exports[`run with options: {"module":"umd"} 1`] = ` + × jest --no-cache + ↳ exit code: 1 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + ts-jest[config] (WARN) TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): + message TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. + PASS ./import-legacy.spec.ts + PASS ./import-star.spec.ts + FAIL ./import-default.spec.ts + ● import default + + expect(received).toBe(expected) // Object.is equality + + Expected: "function" + Received: "undefined" + + 2 | + 3 | test('import default', () => { + > 4 | expect(typeof lib).toBe('function') + | ^ + 5 | expect(lib()).toBe('foo') + 6 | expect(lib.bar).toBe('bar') + 7 | }) + + at Object. (import-default.spec.ts:4:22) + + Test Suites: 1 failed, 2 passed, 3 total + Tests: 1 failed, 2 passed, 3 total + Snapshots: 0 total + Time: XXs + Ran all test suites. + ================================================================================ +`; diff --git a/e2e/__tests__/module-kinds/amd.test.ts b/e2e/__tests__/module-kinds/amd.test.ts new file mode 100644 index 0000000000..b043281ec5 --- /dev/null +++ b/e2e/__tests__/module-kinds/amd.test.ts @@ -0,0 +1,8 @@ +import { runTestForOptions } from './helpers' + +const MODULE_KIND = 'amd' + +runTestForOptions({ module: MODULE_KIND }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: false }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: true }) +runTestForOptions({ module: MODULE_KIND, esModuleInterop: true }) diff --git a/e2e/__tests__/module-kinds/commonjs.test.ts b/e2e/__tests__/module-kinds/commonjs.test.ts new file mode 100644 index 0000000000..d2945a3a2b --- /dev/null +++ b/e2e/__tests__/module-kinds/commonjs.test.ts @@ -0,0 +1,8 @@ +import { runTestForOptions } from './helpers' + +const MODULE_KIND = 'commonjs' + +runTestForOptions({ module: MODULE_KIND }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: false }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: true }) +runTestForOptions({ module: MODULE_KIND, esModuleInterop: true }) diff --git a/e2e/__tests__/module-kinds/es2015.test.ts b/e2e/__tests__/module-kinds/es2015.test.ts new file mode 100644 index 0000000000..f192b26dc0 --- /dev/null +++ b/e2e/__tests__/module-kinds/es2015.test.ts @@ -0,0 +1,8 @@ +import { runTestForOptions } from './helpers' + +const MODULE_KIND = 'es2015' + +runTestForOptions({ module: MODULE_KIND }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: false }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: true }) +runTestForOptions({ module: MODULE_KIND, esModuleInterop: true }) diff --git a/e2e/__tests__/module-kinds/esnext.test.ts b/e2e/__tests__/module-kinds/esnext.test.ts new file mode 100644 index 0000000000..df3743ad11 --- /dev/null +++ b/e2e/__tests__/module-kinds/esnext.test.ts @@ -0,0 +1,8 @@ +import { runTestForOptions } from './helpers' + +const MODULE_KIND = 'esnext' + +runTestForOptions({ module: MODULE_KIND }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: false }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: true }) +runTestForOptions({ module: MODULE_KIND, esModuleInterop: true }) diff --git a/e2e/__tests__/module-kinds/helpers.ts b/e2e/__tests__/module-kinds/helpers.ts new file mode 100644 index 0000000000..1e01b2aff5 --- /dev/null +++ b/e2e/__tests__/module-kinds/helpers.ts @@ -0,0 +1,26 @@ +import { configureTestCase } from '../../__helpers__/test-case' + +// None = 0, +// CommonJS = 1, +// AMD = 2, +// UMD = 3, +// System = 4, +// ES2015 = 5, +// ESNext = 6 + +const testCaseForCompilerOpt = (config: any) => { + return configureTestCase('module-kinds', { + tsJestConfig: { tsConfig: config, diagnostics: { warnOnly: true } }, + noCache: true, + }) +} + +export const runTestForOptions = (options: { + module: string + allowSyntheticDefaultImports?: boolean + esModuleInterop?: boolean +}) => { + test(`run with options: ${JSON.stringify(options)}`, () => { + expect(testCaseForCompilerOpt(options).run()).toMatchSnapshot() + }) +} diff --git a/e2e/__tests__/module-kinds/none.test.ts b/e2e/__tests__/module-kinds/none.test.ts new file mode 100644 index 0000000000..8741a86bcb --- /dev/null +++ b/e2e/__tests__/module-kinds/none.test.ts @@ -0,0 +1,8 @@ +import { runTestForOptions } from './helpers' + +const MODULE_KIND = 'none' + +runTestForOptions({ module: MODULE_KIND }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: false }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: true }) +runTestForOptions({ module: MODULE_KIND, esModuleInterop: true }) diff --git a/e2e/__tests__/module-kinds/system.test.ts b/e2e/__tests__/module-kinds/system.test.ts new file mode 100644 index 0000000000..8534235423 --- /dev/null +++ b/e2e/__tests__/module-kinds/system.test.ts @@ -0,0 +1,8 @@ +import { runTestForOptions } from './helpers' + +const MODULE_KIND = 'system' + +runTestForOptions({ module: MODULE_KIND }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: false }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: true }) +runTestForOptions({ module: MODULE_KIND, esModuleInterop: true }) diff --git a/e2e/__tests__/module-kinds/umd.test.ts b/e2e/__tests__/module-kinds/umd.test.ts new file mode 100644 index 0000000000..fb66c15b56 --- /dev/null +++ b/e2e/__tests__/module-kinds/umd.test.ts @@ -0,0 +1,8 @@ +import { runTestForOptions } from './helpers' + +const MODULE_KIND = 'umd' + +runTestForOptions({ module: MODULE_KIND }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: false }) +runTestForOptions({ module: MODULE_KIND, allowSyntheticDefaultImports: true }) +runTestForOptions({ module: MODULE_KIND, esModuleInterop: true }) diff --git a/scripts/clean.js b/scripts/clean.js index 152df5a9ce..90b6ee88ab 100755 --- a/scripts/clean.js +++ b/scripts/clean.js @@ -22,5 +22,6 @@ removeSync(join(Paths.testsRootDir, '*', 'debug.txt')) removeSync(join(Paths.testsRootDir, '*', 'node_modules')) removeSync(join(Paths.e2eSourceDir, '*', 'node_modules')) removeSync(join(Paths.e2eTemplatesDir, '*', 'node_modules')) +removeSync(Paths.cacheDir) removeSync(Paths.e2eWorkDir) removeSync(Paths.e2eWotkDirLink) diff --git a/scripts/e2e.js b/scripts/e2e.js index dcc9fcb2ac..3e2ad46765 100755 --- a/scripts/e2e.js +++ b/scripts/e2e.js @@ -23,8 +23,13 @@ if (parentArgs.includes('--coverage')) { if (!parentArgs.includes('--runInBand')) parentArgs.push('--runInBand') const prepareOnly = parentArgs.includes('--prepareOnly') +// eslint-disable-next-line no-unused-vars +function enableOptimizations() { + return !!process.env.TS_JEST_E2E_OPTIMIZATIONS +} + function getDirectories(rootDir) { - return fs.readdirSync(rootDir).filter(function(file) { + return fs.readdirSync(rootDir).filter(function (file) { return fs.statSync(path.join(rootDir, file)).isDirectory() }) } @@ -64,10 +69,18 @@ function setupE2e() { ) } + // cleanup files related to old test run + getDirectories(Paths.e2eWorkDir).forEach(name => { + const dir = path.join(Paths.e2eWorkDir, name) + if (dir === Paths.e2eWorkTemplatesDir) return + log('cleaning old artifacts in', name) + fs.removeSync(dir) + }) + // install with `npm ci` in each template, this is the fastest but needs a package lock file, // that is why we end with the npm install of our bundle getDirectories(Paths.e2eTemplatesDir).forEach(name => { - log('checking template ', name) + log('checking template', name) const sourceDir = path.join(Paths.e2eTemplatesDir, name) const dir = path.join(Paths.e2eWorkTemplatesDir, name) const nodeModulesDir = path.join(dir, 'node_modules') diff --git a/src/config/config-set.spec.ts b/src/config/config-set.spec.ts index a357fc9bbe..eef9b851ae 100644 --- a/src/config/config-set.spec.ts +++ b/src/config/config-set.spec.ts @@ -1,6 +1,6 @@ import { testing } from 'bs-logger' import { resolve } from 'path' -import ts, { Diagnostic, ModuleKind, ScriptTarget } from 'typescript' +import ts, { Diagnostic, DiagnosticCategory, ModuleKind, ScriptTarget } from 'typescript' import * as _myModule from '..' import * as fakers from '../__helpers__/fakers' @@ -295,7 +295,7 @@ describe('typescript', () => { target.clear() const cs = createConfigSet({ tsJestConfig: { - tsConfig: { module: 'ES6', esModuleInterop: false, allowSyntheticDefaultImports: false } as any, + tsConfig: { module: 'ES6', esModuleInterop: false } as any, diagnostics: { warnOnly: true, pretty: false }, }, resolve: null, @@ -307,7 +307,7 @@ describe('typescript', () => { }) expect(target.lines.warn.join()).toMatchInlineSnapshot(` "[level:40] TypeScript diagnostics (customize using \`[jest-config].globals.ts-jest.diagnostics\` option): -warning TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. +message TS151001: If you have issues related to imports, you should consider setting \`esModuleInterop\` to \`true\` in your TypeScript configuration file (usually \`tsconfig.json\`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information. " `) }) @@ -540,15 +540,20 @@ Object { describe('raiseDiagnostics', () => { const createTsError = jest.fn( - (list: Diagnostic[]) => new Error(list.map(d => `[${d.code}] ${d.messageText}`).join('\n')), + (list: Diagnostic[]) => new Error(list.map(d => `[TS${d.code}] ${d.messageText}`).join('\n')), ) const filterDiagnostics = jest.fn(list => list) const logger = testing.createLoggerMock() - const diagnostic: Diagnostic = { messageText: 'foo', code: 'TS9999' } as any + const makeDiagnostic = ({ + messageText = 'foo', + code = 9999, + category = DiagnosticCategory.Warning, + }: Partial = {}): Diagnostic => ({ messageText, code, category } as any) it('should throw when warnOnly is false', () => { const { raiseDiagnostics } = createConfigSet({ createTsError, filterDiagnostics }) expect(() => raiseDiagnostics([])).not.toThrow() - expect(() => raiseDiagnostics([diagnostic])).toThrowErrorMatchingInlineSnapshot(`"[TS9999] foo"`) + expect(() => raiseDiagnostics([makeDiagnostic()])).toThrowErrorMatchingInlineSnapshot(`"[TS9999] foo"`) + expect(() => raiseDiagnostics([makeDiagnostic({ category: DiagnosticCategory.Message })])).not.toThrow() }) it('should not throw when warnOnly is true', () => { const { raiseDiagnostics } = createConfigSet({ @@ -559,7 +564,7 @@ describe('raiseDiagnostics', () => { }) logger.target.clear() expect(() => raiseDiagnostics([])).not.toThrow() - expect(() => raiseDiagnostics([diagnostic])).not.toThrow() + expect(() => raiseDiagnostics([makeDiagnostic()])).not.toThrow() expect(logger.target.lines).toMatchInlineSnapshot(` Array [ "[level:40] [TS9999] foo diff --git a/src/config/config-set.ts b/src/config/config-set.ts index 4d1c1debfd..7642850e92 100644 --- a/src/config/config-set.ts +++ b/src/config/config-set.ts @@ -265,12 +265,17 @@ export class ConfigSet { tsJest: { diagnostics: { throws }, }, + compilerModule: { DiagnosticCategory }, } = this return (diagnostics: Diagnostic[], filePath?: string, logger: Logger = this.logger): void | never => { const filteredDiagnostics = filterDiagnostics(diagnostics, filePath) if (filteredDiagnostics.length === 0) return const error = createTsError(filteredDiagnostics) - if (throws) throw error + // only throw if `warnOnly` and it is a warning or error + const importantCategories = [DiagnosticCategory.Warning, DiagnosticCategory.Error] + if (throws && filteredDiagnostics.some(d => importantCategories.includes(d.category))) { + throw error + } logger.warn({ error }, error.message) } } @@ -621,10 +626,19 @@ export class ConfigSet { ? ts.ModuleKind.CommonJS : ts.ModuleKind.ESNext const moduleValue = finalOptions.module == null ? defaultModule : finalOptions.module - if (moduleValue !== forcedOptions.module && !finalOptions.esModuleInterop) { - result.errors.push(this.makeDiagnostic(DiagnosticCodes.ConfigModuleOption, Errors.ConfigNoModuleInterop)) - // at least enable synthetic default imports - finalOptions.allowSyntheticDefaultImports = true + if ( + moduleValue !== forcedOptions.module && + !(finalOptions.esModuleInterop || finalOptions.allowSyntheticDefaultImports) + ) { + result.errors.push( + this.makeDiagnostic(DiagnosticCodes.ConfigModuleOption, Errors.ConfigNoModuleInterop, { + category: ts.DiagnosticCategory.Message, + }), + ) + // at least enable synthetic default imports (except if it's set in the input config) + if (!('allowSyntheticDefaultImports' in config.compilerOptions)) { + finalOptions.allowSyntheticDefaultImports = true + } } // ensure undefined are removed and other values are overridden