From 5d03c4d45852dd9dfeda5990fe2418aba6620435 Mon Sep 17 00:00:00 2001 From: Huafu Gandon Date: Fri, 31 Aug 2018 14:10:32 +0200 Subject: [PATCH] feat(logging): improves log messages + tests --- README.md | 17 +- doc/tech/process/ts-jest.puml | 2 +- e2e/__helpers__/test-case/index.ts | 2 +- ...rocessedFileIo.ts => processed-file-io.ts} | 2 +- .../{RunDescriptor.ts => run-descriptor.ts} | 2 +- .../test-case/{RunResult.ts => run-result.ts} | 18 +- e2e/__helpers__/test-case/runtime.ts | 2 +- e2e/__helpers__/test-case/types.ts | 2 +- e2e/__serializers__/run-result.ts | 2 +- .../__snapshots__/hoisting.test.ts.snap | 54 ++-- .../__snapshots__/logger.test.ts.snap | 281 +++++++++++------- e2e/__tests__/hoisting.test.ts | 4 +- e2e/__tests__/logger.test.ts | 9 +- jest.config.js | 1 + package-lock.json | 12 +- package.json | 4 +- preprocessor.js | 4 +- scripts/lib/spawn-sync.js | 5 +- src/__helpers__/fakers.ts | 2 + src/__helpers__/mocks.ts | 5 + ...ProcessedSource.ts => processed-source.ts} | 0 src/__helpers__/setup.ts | 1 + src/__serializers__/processed-source.ts | 2 +- src/compiler.spec.ts | 47 +-- src/compiler.ts | 70 +++-- src/config/config-set.ts | 48 ++- src/config/create-jest-preset.ts | 9 + src/index.spec.ts | 5 +- src/transformers/hoisting.ts | 8 +- src/ts-jest-transformer.ts | 27 +- src/types.ts | 1 + src/util/__mocks__/logger.ts | 3 + src/util/__snapshots__/backports.spec.ts.snap | 55 +++- src/util/backports.spec.ts | 11 +- src/util/backports.ts | 215 ++++++++------ src/util/debug.spec.ts | 86 ------ src/util/debug.ts | 108 ------- src/util/exit-handler.ts | 53 ---- src/util/hacks.ts | 6 +- src/util/importer.ts | 12 +- src/util/logger.ts | 12 + src/util/messages.ts | 1 + src/util/ts-error.ts | 6 +- src/util/version-checkers.spec.ts | 23 +- src/util/version-checkers.ts | 20 +- tsconfig.json | 17 +- 46 files changed, 657 insertions(+), 619 deletions(-) rename e2e/__helpers__/test-case/{ProcessedFileIo.ts => processed-file-io.ts} (87%) rename e2e/__helpers__/test-case/{RunDescriptor.ts => run-descriptor.ts} (98%) rename e2e/__helpers__/test-case/{RunResult.ts => run-result.ts} (82%) rename src/__helpers__/{ProcessedSource.ts => processed-source.ts} (100%) create mode 100644 src/__helpers__/setup.ts create mode 100644 src/util/__mocks__/logger.ts delete mode 100644 src/util/debug.spec.ts delete mode 100644 src/util/debug.ts delete mode 100644 src/util/exit-handler.ts create mode 100644 src/util/logger.ts diff --git a/README.md b/README.md index ee562da602..6cabc607f6 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,10 @@ - [Angular 2](#angular-2) - [Tips](#tips) - [Importing packages written in TypeScript](#importing-packages-written-in-typescript) + - [Logging](#logging) - [Known Limitations](#known-limitations) - [Known limitations for TS compiler options](#known-limitations-for-ts-compiler-options) - - [`const enum` is not supported](#const-enum-is-not-supported) + - [`const enum` is not supported if `typeCheck` is not enabled](#const-enum-is-not-supported-if-typecheck-is-not-enabled) - [How to Contribute](#how-to-contribute) - [Quickstart to run tests (only if you're working on this package)](#quickstart-to-run-tests-only-if-youre-working-on-this-package) - [License](#license) @@ -364,6 +365,20 @@ your Jest configuration: By default Jest ignores everything in `node_modules`. This setting prevents Jest from ignoring the package you're interested in, in this case `@foo/bar`, while continuing to ignore everything else in `node_modules`. +### Logging + +This package is using [`bs-logger`](https://www.npmjs.com/package/bs-logger). + +Use environment variable `TS_JEST_LOG=xxx` to configure log targets. By default it'll log entries with level _warning_ and above to **stderr**. + +See the examples in [there](https://github.com/huafu/bs-logger#using-targets) to configure different target(s). + +When posting an issue, it's best to join the full log file which you can create in CWD using: +```sh +TS_JEST_LOG=ts-jest.log jest +# or +TS_JEST_LOG=ts-jest.log npm run test +``` ## Known Limitations diff --git a/doc/tech/process/ts-jest.puml b/doc/tech/process/ts-jest.puml index 404ba5b14e..d4dd6c40f5 100644 --- a/doc/tech/process/ts-jest.puml +++ b/doc/tech/process/ts-jest.puml @@ -87,7 +87,7 @@ if (has afterProcess hook?) then (yes) :call afterProcess hook; -> update source; - floating note left + note left if the hook returns something it'll be used as new source diff --git a/e2e/__helpers__/test-case/index.ts b/e2e/__helpers__/test-case/index.ts index 641be676ff..d7fa1b5ed3 100644 --- a/e2e/__helpers__/test-case/index.ts +++ b/e2e/__helpers__/test-case/index.ts @@ -1,5 +1,5 @@ import { RunTestOptions } from './types' -import RunDescriptor from './RunDescriptor' +import RunDescriptor from './run-descriptor' export function configureTestCase( name: string, diff --git a/e2e/__helpers__/test-case/ProcessedFileIo.ts b/e2e/__helpers__/test-case/processed-file-io.ts similarity index 87% rename from e2e/__helpers__/test-case/ProcessedFileIo.ts rename to e2e/__helpers__/test-case/processed-file-io.ts index 6924c0440b..5e0e0e1c68 100644 --- a/e2e/__helpers__/test-case/ProcessedFileIo.ts +++ b/e2e/__helpers__/test-case/processed-file-io.ts @@ -1,4 +1,4 @@ -import ProcessedSource from '../../../src/__helpers__/ProcessedSource' +import ProcessedSource from '../../../src/__helpers__/processed-source' // tslint:disable-next-line:no-default-export export default class ProcessedFileIo extends ProcessedSource { diff --git a/e2e/__helpers__/test-case/RunDescriptor.ts b/e2e/__helpers__/test-case/run-descriptor.ts similarity index 98% rename from e2e/__helpers__/test-case/RunDescriptor.ts rename to e2e/__helpers__/test-case/run-descriptor.ts index 3182aeb2dd..6b78822336 100644 --- a/e2e/__helpers__/test-case/RunDescriptor.ts +++ b/e2e/__helpers__/test-case/run-descriptor.ts @@ -6,7 +6,7 @@ import { } from './types' import { join } from 'path' import * as Paths from '../../../scripts/lib/paths' -import RunResult from './RunResult' +import RunResult from './run-result' import { run } from './runtime' // tslint:disable-next-line:no-default-export diff --git a/e2e/__helpers__/test-case/RunResult.ts b/e2e/__helpers__/test-case/run-result.ts similarity index 82% rename from e2e/__helpers__/test-case/RunResult.ts rename to e2e/__helpers__/test-case/run-result.ts index 17dd64d1d3..7cd3e40616 100644 --- a/e2e/__helpers__/test-case/RunResult.ts +++ b/e2e/__helpers__/test-case/run-result.ts @@ -1,10 +1,10 @@ import { SpawnSyncReturns } from 'child_process' -import ProcessedFileIo from './ProcessedFileIo' +import ProcessedFileIo from './processed-file-io' import { stripAnsiColors, normalizeJestOutput, escapeRegex } from './utils' import { resolve } from 'path' import { readFileSync, realpathSync } from 'fs' -import { LOG_PREFIX } from '../../../src/util/debug' import { tmpdir } from 'os' +import { LogMessage } from 'bs-logger' // tslint:disable-next-line:no-default-export export default class RunResult { @@ -18,13 +18,13 @@ export default class RunResult { env: { [key: string]: string }, }>, ) { } - get logFilePath() { return resolve(this.cwd, 'ts-jest-debug.log') } + get logFilePath() { return resolve(this.cwd, 'ts-jest.log') } get logFileContent() { return readFileSync(this.logFilePath).toString('utf8') } - get normalizedLogFileContent() { - const prefix = ` ${LOG_PREFIX} ` - return this.normalize(this.logFileContent.split(/\n/g).map(s => { - return s.split(prefix).slice(1).join(prefix) - }).join('\n')) + get logFileEntries(): LogMessage[] { + const lines = this.logFileContent.split(/\n/g) + // remove last, empty line + lines.pop() + return lines.map(s => JSON.parse(s)) } get isPass() { return this.status === 0 } get isFail() { return !this.isPass } @@ -35,7 +35,7 @@ export default class RunResult { get stdout() { return stripAnsiColors((this.result.stdout || '').toString()) } get normalizedStdout() { return normalizeJestOutput(this.stdout) } get cmdLine() { - return [this.context.cmd, ...this.context.args].join(' ') + return [this.context.cmd, ...this.context.args].filter(a => !['-u', '--updateSnapshot'].includes(a)).join(' ') } ioFor(relFilePath: string): ProcessedFileIo { diff --git a/e2e/__helpers__/test-case/runtime.ts b/e2e/__helpers__/test-case/runtime.ts index 15dba3f45c..0ab61f8053 100644 --- a/e2e/__helpers__/test-case/runtime.ts +++ b/e2e/__helpers__/test-case/runtime.ts @@ -1,5 +1,5 @@ import { RunTestOptions, PreparedTest } from './types' -import RunResult from './RunResult' +import RunResult from './run-result' import { templateNameForPath } from './utils' import { join, relative, sep } from 'path' import * as Paths from '../../../scripts/lib/paths' diff --git a/e2e/__helpers__/test-case/types.ts b/e2e/__helpers__/test-case/types.ts index 9e643974a5..2851f71e0a 100644 --- a/e2e/__helpers__/test-case/types.ts +++ b/e2e/__helpers__/test-case/types.ts @@ -1,5 +1,5 @@ import { TsJestConfig } from '../../../src/types' -import RunResult from './RunResult' +import RunResult from './run-result' export interface RunTestOptions { template?: string diff --git a/e2e/__serializers__/run-result.ts b/e2e/__serializers__/run-result.ts index 888876cc76..23bb0d16fd 100644 --- a/e2e/__serializers__/run-result.ts +++ b/e2e/__serializers__/run-result.ts @@ -1,4 +1,4 @@ -import RunResult from '../__helpers__/test-case/RunResult' +import RunResult from '../__helpers__/test-case/run-result' export const test = (val: any) => val && val instanceof RunResult export const print = (val: RunResult, serialize: any, indent: any) => { diff --git a/e2e/__tests__/__snapshots__/hoisting.test.ts.snap b/e2e/__tests__/__snapshots__/hoisting.test.ts.snap index b43611d15c..1613f41c09 100644 --- a/e2e/__tests__/__snapshots__/hoisting.test.ts.snap +++ b/e2e/__tests__/__snapshots__/hoisting.test.ts.snap @@ -1,24 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Hoisting jest.mock() & jest.unmock() should pass using template "default" 1`] = ` - √ jest --runInBand - ↳ exit code: 0 - ===[ STDOUT ]=================================================================== - - ===[ STDERR ]=================================================================== - PASS ./hello.spec.ts - hello - √ should have been mocked - - Test Suites: 1 passed, 1 total - Tests: 1 passed, 1 total - Snapshots: 0 total - Time: XXs - Ran all test suites. - ================================================================================ -`; - -exports[`Hoisting jest.mock() & jest.unmock() should pass using template "default" 2`] = ` +exports[`Hoisting jest.mock() & jest.unmock() should pass using template "default": io 1`] = ` ===[ FILE: hello.spec.ts ]====================================================== "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { @@ -79,7 +61,7 @@ exports[`Hoisting jest.mock() & jest.unmock() should pass using template "defaul ================================================================================ `; -exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-babel-6" 1`] = ` +exports[`Hoisting jest.mock() & jest.unmock() should pass using template "default": output 1`] = ` √ jest --runInBand ↳ exit code: 0 ===[ STDOUT ]=================================================================== @@ -97,7 +79,7 @@ exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-b ================================================================================ `; -exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-babel-6" 2`] = ` +exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-babel-6": io 1`] = ` ===[ FILE: hello.spec.ts ]====================================================== "use strict"; @@ -159,7 +141,7 @@ exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-b ================================================================================ `; -exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-babel-7" 1`] = ` +exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-babel-6": output 1`] = ` √ jest --runInBand ↳ exit code: 0 ===[ STDOUT ]=================================================================== @@ -177,7 +159,7 @@ exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-b ================================================================================ `; -exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-babel-7" 2`] = ` +exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-babel-7": io 1`] = ` ===[ FILE: hello.spec.ts ]====================================================== "use strict"; @@ -251,7 +233,7 @@ exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-b ================================================================================ `; -exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-jest-22" 1`] = ` +exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-babel-7": output 1`] = ` √ jest --runInBand ↳ exit code: 0 ===[ STDOUT ]=================================================================== @@ -269,7 +251,7 @@ exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-j ================================================================================ `; -exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-jest-22" 2`] = ` +exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-jest-22": io 1`] = ` ===[ FILE: hello.spec.ts ]====================================================== "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { @@ -330,7 +312,7 @@ exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-j ================================================================================ `; -exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-typescript-2-7" 1`] = ` +exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-jest-22": output 1`] = ` √ jest --runInBand ↳ exit code: 0 ===[ STDOUT ]=================================================================== @@ -348,7 +330,7 @@ exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-t ================================================================================ `; -exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-typescript-2-7" 2`] = ` +exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-typescript-2-7": io 1`] = ` ===[ FILE: hello.spec.ts ]====================================================== "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { @@ -408,3 +390,21 @@ exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-t version: 3 ================================================================================ `; + +exports[`Hoisting jest.mock() & jest.unmock() should pass using template "with-typescript-2-7": output 1`] = ` + √ jest --runInBand + ↳ exit code: 0 + ===[ STDOUT ]=================================================================== + + ===[ STDERR ]=================================================================== + PASS ./hello.spec.ts + hello + √ should have been mocked + + 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__/__snapshots__/logger.test.ts.snap b/e2e/__tests__/__snapshots__/logger.test.ts.snap index e2b267176c..3c9c265000 100644 --- a/e2e/__tests__/__snapshots__/logger.test.ts.snap +++ b/e2e/__tests__/__snapshots__/logger.test.ts.snap @@ -1,122 +1,183 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`TS_JEST_DEBUG should pass and create log file when using tempalte "default" 1`] = ` -"initiailized -Importer.instance creating Importer singleton -checkVersion jest OK { actual: '23.4.2', expected: '>=22 <24' } -created new transformer [object TsJestTransformer<#1>] -backportJestConfig -Importer#tryThese loaded module typescript -Importer#_patch patching typescript -checkVersion typescript OK { actual: '3.0.1', expected: '>=2.7 <4' } -createCompiler without type-checking, config: { version: '24.0.0-beta.0',\\\\n jest:\\\\n { automock: false,\\\\n browser: false,\\\\n cache: true,\\\\n clearMocks: false,\\\\n coveragePathIgnorePatterns: [ '/node_modules/' ],\\\\n cwd:\\\\n '',\\\\n detectLeaks: false,\\\\n detectOpenHandles: false,\\\\n errorOnDeprecated: false,\\\\n filter: null,\\\\n forceCoverageMatch: [],\\\\n globals: {},\\\\n haste: { providesModuleNodeModules: [] },\\\\n moduleDirectories: [ 'node_modules' ],\\\\n moduleFileExtensions: [ 'js', 'json', 'jsx', 'node', 'ts', 'tsx' ],\\\\n moduleNameMapper: {},\\\\n modulePathIgnorePatterns: [],\\\\n prettierPath: null,\\\\n resetMocks: false,\\\\n resetModules: false,\\\\n resolver: null,\\\\n restoreMocks: false,\\\\n rootDir:\\\\n '',\\\\n roots:\\\\n [ '' ],\\\\n runner: 'jest-runner',\\\\n setupFiles: [],\\\\n setupTestFrameworkScriptFile: null,\\\\n skipFilter: false,\\\\n snapshotSerializers: [],\\\\n testEnvironment:\\\\n '/--ts-jest-temp-e2e--/__templates__/default/node_modules/jest-environment-node/build/index.js',\\\\n testEnvironmentOptions: {},\\\\n testLocationInResults: false,\\\\n testMatch:\\\\n [ '**/__tests__/**/*.js?(x)',\\\\n '**/?(*.)+(spec|test).js?(x)',\\\\n '**/__tests__/**/*.ts?(x)',\\\\n '**/?(*.)+(spec|test).ts?(x)' ],\\\\n testPathIgnorePatterns: [ '/node_modules/' ],\\\\n testRegex: '',\\\\n testRunner:\\\\n '/--ts-jest-temp-e2e--/__templates__/default/node_modules/jest-jasmine2/build/index.js',\\\\n testURL: 'about:blank',\\\\n timers: 'real',\\\\n transform: [ [Array] ],\\\\n transformIgnorePatterns: [ '/node_modules/' ],\\\\n watchPathIgnorePatterns: [] },\\\\n tsJest:\\\\n { tsConfig: { kind: 'inline', value: {} },\\\\n babelConfig: undefined,\\\\n diagnostics: { ignoreCodes: [Array], pretty: true },\\\\n typeCheck: false,\\\\n compiler: 'typescript',\\\\n stringifyContentPathRegex: undefined },\\\\n babel: undefined,\\\\n tsconfig: undefined } -readThrough:cache-miss /Hello.spec.ts -compiler#getOutput compiling as isolated module -customTranformer#hoisting /Hello.spec.ts -readThrough:write-caches /Hello.spec.ts cache file /jest_dx/ts-jest-/.js -readThrough:cache-miss /Hello.ts -compiler#getOutput compiling as isolated module -customTranformer#hoisting /Hello.ts -readThrough:write-caches /Hello.ts cache file /jest_dx/ts-jest-/.js -" +exports[`TS_JEST_LOG should pass and create log file when using tempalte "default" 1`] = ` +Array [ + "[level:20] creating jest presets not handling JavaScript files", + "[level:20] creating Importer singleton", + "[level:20] creating jest presets not handling JavaScript files", + "[level:20] checking version of jest: OK", + "[level:20] created new transformer", + "[level:20] computing cache key for /Hello.spec.ts", + "[level:20] backporting config", + "[level:20] normalized jest config", + "[level:20] normalized ts-jest config", + "[level:20] babel is disabled", + "[level:20] loaded module typescript", + "[level:20] patching typescript", + "[level:20] checking version of typescript: OK", + "[level:20] normalized typescript config", + "[level:20] processing /Hello.spec.ts", + "[level:20] creating typescript compiler without type-checking", + "[level:20] will use file caching", + "[level:20] readThrough(): cache miss", + "[level:20] getOutput(): compiling as isolated module", + "[level:20] visitSourceFileNode(): hoisting", + "[level:20] readThrough(): writing caches", + "[level:20] computing cache key for /Hello.ts", + "[level:20] processing /Hello.ts", + "[level:20] readThrough(): cache miss", + "[level:20] getOutput(): compiling as isolated module", + "[level:20] visitSourceFileNode(): hoisting", + "[level:20] readThrough(): writing caches", +] `; -exports[`TS_JEST_DEBUG should pass and create log file when using tempalte "with-babel-6" 1`] = ` -"initiailized -Importer.instance creating Importer singleton -checkVersion jest OK { actual: '23.4.2', expected: '>=22 <24' } -created new transformer [object TsJestTransformer<#1>] -backportJestConfig -Importer#tryThese loaded module babel-core -Importer#_patch patching babel-core -checkVersion babel-core OK { actual: '6.26.3', expected: '>=6 <7 || 7.0.0-bridge.0' } -Importer#tryThese loaded module typescript -Importer#_patch patching typescript -checkVersion typescript OK { actual: '3.0.1', expected: '>=2.7 <4' } -Importer#tryThese loaded module babel-core -Importer#tryThese loaded module babel-jest -Importer#_patch patching babel-jest -checkVersion babel-jest OK { actual: '23.4.2', expected: '>=22 <24' } -createCompiler without type-checking, config: { version: '24.0.0-beta.0',\\\\n jest:\\\\n { automock: false,\\\\n browser: false,\\\\n cache: true,\\\\n clearMocks: false,\\\\n coveragePathIgnorePatterns: [ '/node_modules/' ],\\\\n cwd:\\\\n '',\\\\n detectLeaks: false,\\\\n detectOpenHandles: false,\\\\n errorOnDeprecated: false,\\\\n filter: null,\\\\n forceCoverageMatch: [],\\\\n globals: {},\\\\n haste: { providesModuleNodeModules: [] },\\\\n moduleDirectories: [ 'node_modules' ],\\\\n moduleFileExtensions: [ 'js', 'json', 'jsx', 'node', 'ts', 'tsx' ],\\\\n moduleNameMapper: {},\\\\n modulePathIgnorePatterns: [],\\\\n prettierPath: null,\\\\n resetMocks: false,\\\\n resetModules: false,\\\\n resolver: null,\\\\n restoreMocks: false,\\\\n rootDir:\\\\n '',\\\\n roots:\\\\n [ '' ],\\\\n runner: 'jest-runner',\\\\n setupFiles: [],\\\\n setupTestFrameworkScriptFile: null,\\\\n skipFilter: false,\\\\n snapshotSerializers: [],\\\\n testEnvironment:\\\\n '/--ts-jest-temp-e2e--/__templates__/with-babel-6/node_modules/jest-environment-node/build/index.js',\\\\n testEnvironmentOptions: {},\\\\n testLocationInResults: false,\\\\n testMatch:\\\\n [ '**/__tests__/**/*.js?(x)',\\\\n '**/?(*.)+(spec|test).js?(x)',\\\\n '**/__tests__/**/*.ts?(x)',\\\\n '**/?(*.)+(spec|test).ts?(x)' ],\\\\n testPathIgnorePatterns: [ '/node_modules/' ],\\\\n testRegex: '',\\\\n testRunner:\\\\n '/--ts-jest-temp-e2e--/__templates__/with-babel-6/node_modules/jest-jasmine2/build/index.js',\\\\n testURL: 'about:blank',\\\\n timers: 'real',\\\\n transform: [ [Array] ],\\\\n transformIgnorePatterns: [ '/node_modules/' ],\\\\n watchPathIgnorePatterns: [] },\\\\n tsJest:\\\\n { tsConfig: { kind: 'inline', value: {} },\\\\n babelConfig: { kind: 'file', value: undefined },\\\\n diagnostics: { ignoreCodes: [Array], pretty: true },\\\\n typeCheck: false,\\\\n compiler: 'typescript',\\\\n stringifyContentPathRegex: undefined },\\\\n babel:\\\\n { filename: 'unknown',\\\\n filenameRelative: undefined,\\\\n inputSourceMap: undefined,\\\\n env: {},\\\\n mode: undefined,\\\\n retainLines: false,\\\\n highlightCode: true,\\\\n suppressDeprecationMessages: false,\\\\n presets: [],\\\\n plugins: [],\\\\n ignore: [],\\\\n only: undefined,\\\\n code: true,\\\\n metadata: true,\\\\n ast: true,\\\\n extends: undefined,\\\\n comments: true,\\\\n shouldPrintComment: undefined,\\\\n wrapPluginVisitorMethod: undefined,\\\\n compact: 'auto',\\\\n minified: false,\\\\n sourceMap: undefined,\\\\n sourceMaps: undefined,\\\\n sourceMapTarget: undefined,\\\\n sourceFileName: undefined,\\\\n sourceRoot: undefined,\\\\n babelrc: true,\\\\n sourceType: 'module',\\\\n auxiliaryCommentBefore: undefined,\\\\n auxiliaryCommentAfter: undefined,\\\\n resolveModuleSource: undefined,\\\\n getModuleId: undefined,\\\\n moduleRoot: undefined,\\\\n moduleIds: false,\\\\n moduleId: undefined,\\\\n passPerPreset: false,\\\\n parserOpts: false,\\\\n generatorOpts: false },\\\\n tsconfig: undefined } -readThrough:cache-miss /Hello.spec.ts -compiler#getOutput compiling as isolated module -customTranformer#hoisting /Hello.spec.ts -readThrough:write-caches /Hello.spec.ts cache file /jest_dx/ts-jest-/.js -readThrough:cache-miss /Hello.ts -compiler#getOutput compiling as isolated module -customTranformer#hoisting /Hello.ts -readThrough:write-caches /Hello.ts cache file /jest_dx/ts-jest-/.js -" +exports[`TS_JEST_LOG should pass and create log file when using tempalte "with-babel-6" 1`] = ` +Array [ + "[level:20] creating jest presets not handling JavaScript files", + "[level:20] creating Importer singleton", + "[level:20] creating jest presets not handling JavaScript files", + "[level:20] checking version of jest: OK", + "[level:20] created new transformer", + "[level:20] computing cache key for /Hello.spec.ts", + "[level:20] backporting config", + "[level:20] normalized jest config", + "[level:20] normalized ts-jest config", + "[level:20] loaded module babel-core", + "[level:20] patching babel-core", + "[level:20] checking version of babel-core: OK", + "[level:30] patched babel-core/lib/transformation/file", + "[level:20] normalized babel config", + "[level:20] loaded module typescript", + "[level:20] patching typescript", + "[level:20] checking version of typescript: OK", + "[level:20] normalized typescript config", + "[level:20] processing /Hello.spec.ts", + "[level:20] creating babel-jest transformer", + "[level:20] loaded module babel-core", + "[level:20] loaded module babel-jest", + "[level:20] patching babel-jest", + "[level:20] checking version of babel-jest: OK", + "[level:20] creating typescript compiler without type-checking", + "[level:20] will use file caching", + "[level:20] readThrough(): cache miss", + "[level:20] getOutput(): compiling as isolated module", + "[level:20] visitSourceFileNode(): hoisting", + "[level:20] readThrough(): writing caches", + "[level:20] calling babel-jest processor", + "[level:20] computing cache key for /Hello.ts", + "[level:20] processing /Hello.ts", + "[level:20] readThrough(): cache miss", + "[level:20] getOutput(): compiling as isolated module", + "[level:20] visitSourceFileNode(): hoisting", + "[level:20] readThrough(): writing caches", + "[level:20] calling babel-jest processor", +] `; -exports[`TS_JEST_DEBUG should pass and create log file when using tempalte "with-babel-7" 1`] = ` -"initiailized -Importer.instance creating Importer singleton -checkVersion jest OK { actual: '23.4.2', expected: '>=22 <24' } -created new transformer [object TsJestTransformer<#1>] -backportJestConfig -Importer#tryThese loaded module babel-core -Importer#_patch patching babel-core -checkVersion babel-core OK { actual: '7.0.0-bridge.0',\\\\n expected: '>=6 <7 || 7.0.0-bridge.0' } -Importer#tryThese loaded module typescript -Importer#_patch patching typescript -checkVersion typescript OK { actual: '3.0.1', expected: '>=2.7 <4' } -Importer#tryThese loaded module babel-core -Importer#tryThese loaded module babel-jest -Importer#_patch patching babel-jest -checkVersion babel-jest OK { actual: '23.4.2', expected: '>=22 <24' } -createCompiler without type-checking, config: { version: '24.0.0-beta.0',\\\\n jest:\\\\n { automock: false,\\\\n browser: false,\\\\n cache: true,\\\\n clearMocks: false,\\\\n coveragePathIgnorePatterns: [ '/node_modules/' ],\\\\n cwd:\\\\n '',\\\\n detectLeaks: false,\\\\n detectOpenHandles: false,\\\\n errorOnDeprecated: false,\\\\n filter: null,\\\\n forceCoverageMatch: [],\\\\n globals: {},\\\\n haste: { providesModuleNodeModules: [] },\\\\n moduleDirectories: [ 'node_modules' ],\\\\n moduleFileExtensions: [ 'js', 'json', 'jsx', 'node', 'ts', 'tsx' ],\\\\n moduleNameMapper: {},\\\\n modulePathIgnorePatterns: [],\\\\n prettierPath: null,\\\\n resetMocks: false,\\\\n resetModules: false,\\\\n resolver: null,\\\\n restoreMocks: false,\\\\n rootDir:\\\\n '',\\\\n roots:\\\\n [ '' ],\\\\n runner: 'jest-runner',\\\\n setupFiles: [],\\\\n setupTestFrameworkScriptFile: null,\\\\n skipFilter: false,\\\\n snapshotSerializers: [],\\\\n testEnvironment:\\\\n '/--ts-jest-temp-e2e--/__templates__/with-babel-7/node_modules/jest-environment-node/build/index.js',\\\\n testEnvironmentOptions: {},\\\\n testLocationInResults: false,\\\\n testMatch:\\\\n [ '**/__tests__/**/*.js?(x)',\\\\n '**/?(*.)+(spec|test).js?(x)',\\\\n '**/__tests__/**/*.ts?(x)',\\\\n '**/?(*.)+(spec|test).ts?(x)' ],\\\\n testPathIgnorePatterns: [ '/node_modules/' ],\\\\n testRegex: '',\\\\n testRunner:\\\\n '/--ts-jest-temp-e2e--/__templates__/with-babel-7/node_modules/jest-jasmine2/build/index.js',\\\\n testURL: 'about:blank',\\\\n timers: 'real',\\\\n transform: [ [Array] ],\\\\n transformIgnorePatterns: [ '/node_modules/' ],\\\\n watchPathIgnorePatterns: [] },\\\\n tsJest:\\\\n { tsConfig: { kind: 'inline', value: {} },\\\\n babelConfig: { kind: 'file', value: undefined },\\\\n diagnostics: { ignoreCodes: [Array], pretty: true },\\\\n typeCheck: false,\\\\n compiler: 'typescript',\\\\n stringifyContentPathRegex: undefined },\\\\n babel:\\\\n { cwd:\\\\n '',\\\\n babelrc: false,\\\\n configFile: false,\\\\n passPerPreset: false,\\\\n envName: 'test',\\\\n root:\\\\n '',\\\\n plugins: [],\\\\n presets: [] },\\\\n tsconfig: undefined } -readThrough:cache-miss /Hello.spec.ts -compiler#getOutput compiling as isolated module -customTranformer#hoisting /Hello.spec.ts -readThrough:write-caches /Hello.spec.ts cache file /jest_dx/ts-jest-/.js -readThrough:cache-miss /Hello.ts -compiler#getOutput compiling as isolated module -customTranformer#hoisting /Hello.ts -readThrough:write-caches /Hello.ts cache file /jest_dx/ts-jest-/.js -" +exports[`TS_JEST_LOG should pass and create log file when using tempalte "with-babel-7" 1`] = ` +Array [ + "[level:20] creating jest presets not handling JavaScript files", + "[level:20] creating Importer singleton", + "[level:20] creating jest presets not handling JavaScript files", + "[level:20] checking version of jest: OK", + "[level:20] created new transformer", + "[level:20] computing cache key for /Hello.spec.ts", + "[level:20] backporting config", + "[level:20] normalized jest config", + "[level:20] normalized ts-jest config", + "[level:20] loaded module babel-core", + "[level:20] patching babel-core", + "[level:20] checking version of babel-core: OK", + "[level:20] normalized babel config", + "[level:20] loaded module typescript", + "[level:20] patching typescript", + "[level:20] checking version of typescript: OK", + "[level:20] normalized typescript config", + "[level:20] processing /Hello.spec.ts", + "[level:20] creating babel-jest transformer", + "[level:20] loaded module babel-core", + "[level:20] loaded module babel-jest", + "[level:20] patching babel-jest", + "[level:20] checking version of babel-jest: OK", + "[level:20] creating typescript compiler without type-checking", + "[level:20] will use file caching", + "[level:20] readThrough(): cache miss", + "[level:20] getOutput(): compiling as isolated module", + "[level:20] visitSourceFileNode(): hoisting", + "[level:20] readThrough(): writing caches", + "[level:20] calling babel-jest processor", + "[level:20] computing cache key for /Hello.ts", + "[level:20] processing /Hello.ts", + "[level:20] readThrough(): cache miss", + "[level:20] getOutput(): compiling as isolated module", + "[level:20] visitSourceFileNode(): hoisting", + "[level:20] readThrough(): writing caches", + "[level:20] calling babel-jest processor", +] `; -exports[`TS_JEST_DEBUG should pass and create log file when using tempalte "with-jest-22" 1`] = ` -"initiailized -Importer.instance creating Importer singleton -checkVersion jest OK { actual: '22.4.4', expected: '>=22 <24' } -created new transformer [object TsJestTransformer<#1>] -backportJestConfig -Importer#tryThese loaded module typescript -Importer#_patch patching typescript -checkVersion typescript OK { actual: '3.0.1', expected: '>=2.7 <4' } -createCompiler without type-checking, config: { version: '24.0.0-beta.0',\\\\n jest:\\\\n { automock: false,\\\\n browser: false,\\\\n cache: true,\\\\n clearMocks: false,\\\\n coveragePathIgnorePatterns: [ '/node_modules/' ],\\\\n cwd:\\\\n '',\\\\n detectLeaks: false,\\\\n forceCoverageMatch: [],\\\\n globals: {},\\\\n haste: { providesModuleNodeModules: [] },\\\\n moduleDirectories: [ 'node_modules' ],\\\\n moduleFileExtensions: [ 'js', 'json', 'jsx', 'node', 'ts', 'tsx' ],\\\\n moduleNameMapper: {},\\\\n modulePathIgnorePatterns: [],\\\\n resetMocks: false,\\\\n resetModules: false,\\\\n restoreMocks: false,\\\\n rootDir:\\\\n '',\\\\n roots:\\\\n [ '' ],\\\\n runner: 'jest-runner',\\\\n setupFiles: [],\\\\n snapshotSerializers: [],\\\\n testEnvironment:\\\\n '/--ts-jest-temp-e2e--/__templates__/with-jest-22/node_modules/jest-environment-node/build/index.js',\\\\n testEnvironmentOptions: {},\\\\n testLocationInResults: false,\\\\n testMatch:\\\\n [ '**/__tests__/**/*.js?(x)',\\\\n '**/?(*.)+(spec|test).js?(x)',\\\\n '**/__tests__/**/*.ts?(x)',\\\\n '**/?(*.)+(spec|test).ts?(x)' ],\\\\n testPathIgnorePatterns: [ '/node_modules/' ],\\\\n testRegex: '',\\\\n testRunner:\\\\n '/--ts-jest-temp-e2e--/__templates__/with-jest-22/node_modules/jest-jasmine2/build/index.js',\\\\n testURL: 'about:blank',\\\\n timers: 'real',\\\\n transform: [ [Array] ],\\\\n transformIgnorePatterns: [ '/node_modules/' ],\\\\n watchPathIgnorePatterns: [] },\\\\n tsJest:\\\\n { tsConfig: { kind: 'inline', value: {} },\\\\n babelConfig: undefined,\\\\n diagnostics: { ignoreCodes: [Array], pretty: true },\\\\n typeCheck: false,\\\\n compiler: 'typescript',\\\\n stringifyContentPathRegex: undefined },\\\\n babel: undefined,\\\\n tsconfig: undefined } -readThrough:cache-miss /Hello.spec.ts -compiler#getOutput compiling as isolated module -customTranformer#hoisting /Hello.spec.ts -readThrough:write-caches /Hello.spec.ts cache file /jest_dx/ts-jest-/.js -readThrough:cache-miss /Hello.ts -compiler#getOutput compiling as isolated module -customTranformer#hoisting /Hello.ts -readThrough:write-caches /Hello.ts cache file /jest_dx/ts-jest-/.js -" +exports[`TS_JEST_LOG should pass and create log file when using tempalte "with-jest-22" 1`] = ` +Array [ + "[level:20] creating Importer singleton", + "[level:20] creating jest presets not handling JavaScript files", + "[level:20] checking version of jest: OK", + "[level:20] created new transformer", + "[level:20] computing cache key for /Hello.spec.ts", + "[level:20] backporting config", + "[level:20] normalized jest config", + "[level:20] normalized ts-jest config", + "[level:20] babel is disabled", + "[level:20] loaded module typescript", + "[level:20] patching typescript", + "[level:20] checking version of typescript: OK", + "[level:20] normalized typescript config", + "[level:20] processing /Hello.spec.ts", + "[level:20] creating typescript compiler without type-checking", + "[level:20] will use file caching", + "[level:20] readThrough(): cache miss", + "[level:20] getOutput(): compiling as isolated module", + "[level:20] visitSourceFileNode(): hoisting", + "[level:20] readThrough(): writing caches", + "[level:20] computing cache key for /Hello.ts", + "[level:20] processing /Hello.ts", + "[level:20] readThrough(): cache miss", + "[level:20] getOutput(): compiling as isolated module", + "[level:20] visitSourceFileNode(): hoisting", + "[level:20] readThrough(): writing caches", +] `; -exports[`TS_JEST_DEBUG should pass and create log file when using tempalte "with-typescript-2-7" 1`] = ` -"initiailized -Importer.instance creating Importer singleton -checkVersion jest OK { actual: '23.4.2', expected: '>=22 <24' } -created new transformer [object TsJestTransformer<#1>] -backportJestConfig -Importer#tryThese loaded module typescript -Importer#_patch patching typescript -checkVersion typescript OK { actual: '2.7.2', expected: '>=2.7 <4' } -createCompiler without type-checking, config: { version: '24.0.0-beta.0',\\\\n jest:\\\\n { automock: false,\\\\n browser: false,\\\\n cache: true,\\\\n clearMocks: false,\\\\n coveragePathIgnorePatterns: [ '/node_modules/' ],\\\\n cwd:\\\\n '',\\\\n detectLeaks: false,\\\\n detectOpenHandles: false,\\\\n errorOnDeprecated: false,\\\\n filter: null,\\\\n forceCoverageMatch: [],\\\\n globals: {},\\\\n haste: { providesModuleNodeModules: [] },\\\\n moduleDirectories: [ 'node_modules' ],\\\\n moduleFileExtensions: [ 'js', 'json', 'jsx', 'node', 'ts', 'tsx' ],\\\\n moduleNameMapper: {},\\\\n modulePathIgnorePatterns: [],\\\\n prettierPath: null,\\\\n resetMocks: false,\\\\n resetModules: false,\\\\n resolver: null,\\\\n restoreMocks: false,\\\\n rootDir:\\\\n '',\\\\n roots:\\\\n [ '' ],\\\\n runner: 'jest-runner',\\\\n setupFiles: [],\\\\n setupTestFrameworkScriptFile: null,\\\\n skipFilter: false,\\\\n snapshotSerializers: [],\\\\n testEnvironment:\\\\n '/--ts-jest-temp-e2e--/__templates__/with-typescript-2-7/node_modules/jest-environment-node/build/index.js',\\\\n testEnvironmentOptions: {},\\\\n testLocationInResults: false,\\\\n testMatch:\\\\n [ '**/__tests__/**/*.js?(x)',\\\\n '**/?(*.)+(spec|test).js?(x)',\\\\n '**/__tests__/**/*.ts?(x)',\\\\n '**/?(*.)+(spec|test).ts?(x)' ],\\\\n testPathIgnorePatterns: [ '/node_modules/' ],\\\\n testRegex: '',\\\\n testRunner:\\\\n '/--ts-jest-temp-e2e--/__templates__/with-typescript-2-7/node_modules/jest-jasmine2/build/index.js',\\\\n testURL: 'about:blank',\\\\n timers: 'real',\\\\n transform: [ [Array] ],\\\\n transformIgnorePatterns: [ '/node_modules/' ],\\\\n watchPathIgnorePatterns: [] },\\\\n tsJest:\\\\n { tsConfig: { kind: 'inline', value: {} },\\\\n babelConfig: undefined,\\\\n diagnostics: { pretty: true, ignoreCodes: [Array], pathRegex: undefined },\\\\n typeCheck: false,\\\\n compiler: 'typescript',\\\\n stringifyContentPathRegex: undefined },\\\\n babel: undefined,\\\\n tsconfig: undefined } -readThrough:cache-miss /Hello.spec.ts -compiler#getOutput compiling as isolated module -customTranformer#hoisting /Hello.spec.ts -readThrough:write-caches /Hello.spec.ts cache file /jest_dx/ts-jest-/.js -readThrough:cache-miss /Hello.ts -compiler#getOutput compiling as isolated module -customTranformer#hoisting /Hello.ts -readThrough:write-caches /Hello.ts cache file /jest_dx/ts-jest-/.js -" +exports[`TS_JEST_LOG should pass and create log file when using tempalte "with-typescript-2-7" 1`] = ` +Array [ + "[level:20] creating jest presets not handling JavaScript files", + "[level:20] creating Importer singleton", + "[level:20] creating jest presets not handling JavaScript files", + "[level:20] checking version of jest: OK", + "[level:20] created new transformer", + "[level:20] computing cache key for /Hello.spec.ts", + "[level:20] backporting config", + "[level:20] normalized jest config", + "[level:20] normalized ts-jest config", + "[level:20] babel is disabled", + "[level:20] loaded module typescript", + "[level:20] patching typescript", + "[level:20] checking version of typescript: OK", + "[level:20] normalized typescript config", + "[level:20] processing /Hello.spec.ts", + "[level:20] creating typescript compiler without type-checking", + "[level:20] will use file caching", + "[level:20] readThrough(): cache miss", + "[level:20] getOutput(): compiling as isolated module", + "[level:20] visitSourceFileNode(): hoisting", + "[level:20] readThrough(): writing caches", + "[level:20] computing cache key for /Hello.ts", + "[level:20] processing /Hello.ts", + "[level:20] readThrough(): cache miss", + "[level:20] getOutput(): compiling as isolated module", + "[level:20] visitSourceFileNode(): hoisting", + "[level:20] readThrough(): writing caches", +] `; exports[`With unsupported version test should pass using template "with-unsupported-version" 1`] = ` @@ -125,7 +186,7 @@ exports[`With unsupported version test should pass using template "with-unsuppor ===[ STDOUT ]=================================================================== ===[ STDERR ]=================================================================== - ts-jest: Version 2.5.3 of typescript installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=2.7.0 <4.0.0). Please do not report issues in ts-jest if you are using unsupported versions. + ts-jest[versions] (WARN) Version 2.5.3 of typescript installed has not been tested with ts-jest. If you're experiencing issues, consider using a supported version (>=2.7.0 <4.0.0). Please do not report issues in ts-jest if you are using unsupported versions. PASS ./Hello.spec.ts Hello Class √ should create a new Hello diff --git a/e2e/__tests__/hoisting.test.ts b/e2e/__tests__/hoisting.test.ts index 3f5b80b2a6..c58eff4c8d 100644 --- a/e2e/__tests__/hoisting.test.ts +++ b/e2e/__tests__/hoisting.test.ts @@ -8,8 +8,8 @@ describe('Hoisting jest.mock() & jest.unmock()', () => { it(testLabel, () => { const result = runTest() expect(result.status).toBe(0) - expect(result).toMatchSnapshot() - expect(result.ioFor('hello.spec.ts')).toMatchSnapshot() + expect(result).toMatchSnapshot('output') + expect(result.ioFor('hello.spec.ts')).toMatchSnapshot('io') }) }) }) diff --git a/e2e/__tests__/logger.test.ts b/e2e/__tests__/logger.test.ts index 07adcae80a..6549f890ad 100644 --- a/e2e/__tests__/logger.test.ts +++ b/e2e/__tests__/logger.test.ts @@ -1,6 +1,7 @@ import { configureTestCase } from '../__helpers__/test-case' import { PackageSets, allValidPackageSets } from '../__helpers__/templates' import { existsSync } from 'fs' +import { LogContexts } from 'bs-logger' describe('With unsupported version test', () => { const testCase = configureTestCase('simple') @@ -14,15 +15,17 @@ describe('With unsupported version test', () => { }) }) -describe('TS_JEST_DEBUG', () => { - const testCase = configureTestCase('simple', { env: { TS_JEST_DEBUG: 'true' } }) +describe('TS_JEST_LOG', () => { + const testCase = configureTestCase('simple', { env: { TS_JEST_LOG: 'ts-jest.log' } }) testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { templateName }) => { it(`should pass and create log file when using tempalte "${templateName}"`, () => { const result = runTest() expect(result.status).toBe(0) expect(existsSync(result.logFilePath)) - expect(result.normalizedLogFileContent).toMatchSnapshot() + expect(result.logFileEntries.map( + e => result.normalize(`[level:${e.context[LogContexts.logLevel]}] ${e.message}`), + )).toMatchSnapshot() }) }) }) diff --git a/jest.config.js b/jest.config.js index 7d0ef4c117..b11cb8a378 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,6 @@ module.exports = { rootDir: '.', + setupTestFrameworkScriptFile: '/src/__helpers__/setup.ts', transform: { '\\.ts$': '/dist/index.js', }, diff --git a/package-lock.json b/package-lock.json index ff2495eb0d..282159ee9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -853,6 +853,15 @@ "resolve": "1.1.7" } }, + "bs-logger": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.3.tgz", + "integrity": "sha512-R0572NTYtxTIJ412QkAA0JeMvVUHwGBXcWXdO6d115Etn35OJlBEH5NGBBzJbvyVaFPMy3L4H0KIPJpPvSPMYg==", + "requires": { + "fast-json-stable-stringify": "^2.0.0", + "tslib": "^1.9.3" + } + }, "bser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/bser/-/bser-2.0.0.tgz", @@ -6748,8 +6757,7 @@ "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", - "dev": true + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, "tslint": { "version": "5.11.0", diff --git a/package.json b/package.json index 367c7ba677..c628410ad2 100644 --- a/package.json +++ b/package.json @@ -42,11 +42,13 @@ }, "homepage": "https://github.com/kulshekhar/ts-jest#readme", "dependencies": { + "bs-logger": "^0.2.3", "buffer-from": "^1.1.1", "fast-json-stable-stringify": "^2.0.0", "make-error": "^1.3.4", "mkdirp": "^0.5.1", - "semver": "^5.5.1" + "semver": "^5.5.1", + "tslib": "^1.9.3" }, "peerDependencies": { "babel-jest": ">=22 <24", diff --git a/preprocessor.js b/preprocessor.js index 2b1f030c5f..19a071d4bd 100644 --- a/preprocessor.js +++ b/preprocessor.js @@ -1,7 +1,5 @@ console.warn( - 'ts-jest:', - '[deprecated]', - 'Replace any occurrences of "ts-jest/dist/preprocessor.js" or ' + + 'ts-jest[main] (WARN) Replace any occurrences of "ts-jest/dist/preprocessor.js" or ' + ' "/node_modules/ts-jest/preprocessor.js"' + ' in the \'transform\' section of your Jest config with just "ts-jest".' ) diff --git a/scripts/lib/spawn-sync.js b/scripts/lib/spawn-sync.js index 11cf45a16a..2b66872b93 100644 --- a/scripts/lib/spawn-sync.js +++ b/scripts/lib/spawn-sync.js @@ -11,7 +11,10 @@ const spawnSync = (...args) => { if (res.status !== 0) { let msg = 'unknown error' try { - msg = res.stderr.toString('utf8') + msg = + res.stderr.toString('utf8').trim() || + res.stdout.toString('utf8').trim() || + msg } catch (err) { null } diff --git a/src/__helpers__/fakers.ts b/src/__helpers__/fakers.ts index 8ea599d36c..e5e3c0d058 100644 --- a/src/__helpers__/fakers.ts +++ b/src/__helpers__/fakers.ts @@ -1,6 +1,8 @@ import { TsJestGlobalOptions, BabelConfig, TsJestConfig } from '../types' import { resolve } from 'path' import { ImportReasons } from '../util/messages' +import { Writable } from 'stream' +import { LogTarget, LogMessage } from 'bs-logger' export function filePath(relPath: string): string { return resolve(__dirname, '..', '..', relPath) diff --git a/src/__helpers__/mocks.ts b/src/__helpers__/mocks.ts index 8c578653ce..27d85ac022 100644 --- a/src/__helpers__/mocks.ts +++ b/src/__helpers__/mocks.ts @@ -1,3 +1,6 @@ +import { rootLogger } from '../util/logger' +import { testing } from 'bs-logger' + // typings helper export function mocked( val: T, @@ -9,3 +12,5 @@ export function spied( ): T extends (...args: any[]) => any ? jest.SpyInstance : jest.Mocked { return val as any } + +export const logTargetMock = () => (rootLogger as testing.LoggerMock).target diff --git a/src/__helpers__/ProcessedSource.ts b/src/__helpers__/processed-source.ts similarity index 100% rename from src/__helpers__/ProcessedSource.ts rename to src/__helpers__/processed-source.ts diff --git a/src/__helpers__/setup.ts b/src/__helpers__/setup.ts new file mode 100644 index 0000000000..a0fd1e342d --- /dev/null +++ b/src/__helpers__/setup.ts @@ -0,0 +1 @@ +jest.mock('../util/logger') diff --git a/src/__serializers__/processed-source.ts b/src/__serializers__/processed-source.ts index 7c05d78a79..263be032c2 100644 --- a/src/__serializers__/processed-source.ts +++ b/src/__serializers__/processed-source.ts @@ -1,5 +1,5 @@ import { safeDump } from 'js-yaml' -import ProcessedSource from '../__helpers__/ProcessedSource' +import ProcessedSource from '../__helpers__/processed-source' export const test = (val: any) => val && val instanceof ProcessedSource export const print = (val: ProcessedSource, serialize: any, indent: any) => { diff --git a/src/compiler.spec.ts b/src/compiler.spec.ts index 3d3e6657b6..b450d3003b 100644 --- a/src/compiler.spec.ts +++ b/src/compiler.spec.ts @@ -3,12 +3,13 @@ import { TsJestGlobalOptions } from './types' import { ConfigSet } from './config/config-set' import * as fakers from './__helpers__/fakers' import { createCompiler } from './compiler' -import { relativeToRoot, tempDir, ROOT } from './__helpers__/path' -import { __setup } from './util/debug' -import ProcessedSource from './__helpers__/ProcessedSource' +import { relativeToRoot, tempDir } from './__helpers__/path' +import ProcessedSource from './__helpers__/processed-source' +import { logTargetMock } from './__helpers__/mocks' -// not really unit-testing here, but it's hard to mock all those values :-D +const logTarget = logTargetMock() +// not really unit-testing here, but it's hard to mock all those values :-D function makeCompiler({ jestConfig, tsJestConfig, @@ -30,11 +31,8 @@ function makeCompiler({ return createCompiler(cs) } -const logger = jest.fn() -__setup({ logger }) - beforeEach(() => { - logger.mockClear() + logTarget.clear() }) describe('typeCheck', () => { @@ -81,22 +79,27 @@ describe('cache', () => { it('should use the cache', () => { const compiled1 = compiler.compile(source, __filename) - expect(logger.mock.calls.map(callArgs => callArgs[2])).toEqual([ - 'readThrough:cache-miss', - 'compiler#getOutput', - 'customTranformer#hoisting', - 'readThrough:write-caches', - ]) + expect(logTarget.lines).toMatchInlineSnapshot(` +Array [ + "[level:20] readThrough(): cache miss +", + "[level:20] getOutput(): compiling as isolated module +", + "[level:20] visitSourceFileNode(): hoisting +", + "[level:20] readThrough(): writing caches +", +] +`) - logger.mockClear() + logTarget.clear() const compiled2 = compiler.compile(source, __filename) - expect(logger).toHaveBeenCalledTimes(1) - expect(logger).toHaveBeenCalledWith( - 'log', - 'ts-jest:', - 'readThrough:cache-hit', - __filename, - ) + expect(logTarget.lines).toMatchInlineSnapshot(` +Array [ + "[level:20] readThrough(): cache hit +", +] +`) expect(new ProcessedSource(compiled1, __filename)).toMatchInlineSnapshot(` ===[ FILE: src/compiler.spec.ts ]=============================================== diff --git a/src/compiler.ts b/src/compiler.ts index 8f7be4bebe..74331a2b5c 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -1,7 +1,8 @@ /** * This code is heavilly inspired from * https://github.com/JsCommunity/make-error/blob/v1.3.4/index.js - * Below is the original license: + * ...but more modified than expected :-D + * Below is the original license anyway: * * --- * @@ -34,12 +35,12 @@ import mkdirp = require('mkdirp') import bufferFrom from 'buffer-from' import stableStringify = require('fast-json-stable-stringify') import _ts, { CustomTransformers } from 'typescript' -import { wrapWithDebug, debug } from './util/debug' import { ConfigSet } from './config/config-set' import { sha1 } from './util/sha1' import { TsCompiler, MemoryCache, TypeInfo } from './types' import { Errors, interpolate } from './util/messages' import { factory as customTransformersFactory } from './transformers' +import { Logger, LogContexts, LogLevels } from 'bs-logger' const hasOwn = Object.prototype.hasOwnProperty @@ -47,11 +48,11 @@ const hasOwn = Object.prototype.hasOwnProperty * Register TypeScript compiler. */ export function createCompiler(configs: ConfigSet): TsCompiler { - debug( - 'createCompiler', + const logger = configs.logger.child({ namespace: 'ts-compiler' }) + logger.debug( + 'creating typescript compiler', configs.tsJest.typeCheck ? 'with' : 'without', - 'type-checking, config:', - configs.toJSON(), + 'type-checking', ) const cachedir = configs.tsCacheDir @@ -98,7 +99,7 @@ export function createCompiler(configs: ConfigSet): TsCompiler { fileName: string, lineOffset = 0, ): SourceOutput => { - debug(`compiler#getOutput`, 'compiling as isolated module') + logger.debug({ fileName }, 'getOutput(): compiling as isolated module') const result = ts.transpileModule(code, { fileName, transformers, @@ -129,7 +130,7 @@ export function createCompiler(configs: ConfigSet): TsCompiler { if (configs.tsJest.typeCheck) { // Set the file contents into cache. const updateMemoryCache = (code: string, fileName: string) => { - debug(`compiler#updateMemoryCache`, fileName) + logger.debug({ fileName }, `updateMemoryCache()`) if (memoryCache.contents[fileName] !== code) { memoryCache.contents[fileName] = code memoryCache.versions[fileName] = @@ -138,6 +139,11 @@ export function createCompiler(configs: ConfigSet): TsCompiler { } // Create the compiler host for type checking. + const serviceHostCtx = { + [LogContexts.logLevel]: LogLevels.debug, + namespace: 'ts:serviceHost', + call: null, + } const serviceHost = { getScriptFileNames: () => Object.keys(memoryCache.versions), getScriptVersion: (fileName: string) => { @@ -154,7 +160,12 @@ export function createCompiler(configs: ConfigSet): TsCompiler { }, getScriptSnapshot(fileName: string) { const hit = hasOwn.call(memoryCache.contents, fileName) - debug(`compiler#getScriptSnapshot`, 'cache', hit ? 'hit' : 'miss') + logger.debug( + { fileName, cacheHit: hit }, + `getScriptSnapshot():`, + 'cache', + hit ? 'hit' : 'miss', + ) // Read contents from TypeScript memory cache. if (!hit) { memoryCache.contents[fileName] = ts.sys.readFile(fileName) @@ -166,11 +177,23 @@ export function createCompiler(configs: ConfigSet): TsCompiler { } return ts.ScriptSnapshot.fromString(contents) }, - fileExists: wrapWithDebug('fileExists', ts.sys.fileExists), - readFile: wrapWithDebug('readFile', ts.sys.readFile), - readDirectory: wrapWithDebug('readDirectory', ts.sys.readDirectory), - getDirectories: wrapWithDebug('getDirectories', ts.sys.getDirectories), - directoryExists: wrapWithDebug('directoryExists', ts.sys.directoryExists), + fileExists: logger.wrap(serviceHostCtx, 'fileExists', ts.sys.fileExists), + readFile: logger.wrap(serviceHostCtx, 'readFile', ts.sys.readFile), + readDirectory: logger.wrap( + serviceHostCtx, + 'readDirectory', + ts.sys.readDirectory, + ), + getDirectories: logger.wrap( + serviceHostCtx, + 'getDirectories', + ts.sys.getDirectories, + ), + directoryExists: logger.wrap( + serviceHostCtx, + 'directoryExists', + ts.sys.directoryExists, + ), getNewLine: () => '\n', getCurrentDirectory: () => cwd, getCompilationSettings: () => compilerOptions, @@ -178,18 +201,21 @@ export function createCompiler(configs: ConfigSet): TsCompiler { getCustomTransformers: () => transformers, } - debug(`createCompiler`, 'creating language service') + logger.debug('creating language service') const service = ts.createLanguageService(serviceHost) getOutput = (code: string, fileName: string, lineOffset: number = 0) => { - debug(`compiler#getOutput`, 'compiling using language service', fileName) + logger.debug( + { fileName }, + 'getOutput(): compiling using language service', + ) // Must set memory cache before attempting to read file. updateMemoryCache(code, fileName) const output = service.getEmitOutput(fileName) if (configs.shouldReportDiagnostic(fileName)) { - debug(`compiler#getOutput`, 'computing diagnostics', fileName) + logger.debug({ fileName }, 'getOutput(): computing diagnostics') // Get the relevant diagnostics - this is 3x faster than `getPreEmitDiagnostics`. const diagnostics = service .getCompilerOptionsDiagnostics() @@ -236,6 +262,7 @@ export function createCompiler(configs: ConfigSet): TsCompiler { getOutput, getExtension, cwd, + logger, ) return { cwd, compile, getTypeInfo, extensions, cachedir, ts } } @@ -258,10 +285,11 @@ function readThrough( ) => SourceOutput, getExtension: (fileName: string) => string, cwd: string, + logger: Logger, ) { if (!cachedir) { return (code: string, fileName: string, lineOffset?: number) => { - debug('readThrough:no-cache', fileName) + logger.debug({ fileName }, 'readThrough(): no cache') const [value, sourceMap] = compile(code, fileName, lineOffset) const output = updateOutput(value, fileName, sourceMap, getExtension, cwd) @@ -283,17 +311,17 @@ function readThrough( try { const output = readFileSync(outputPath, 'utf8') if (isValidCacheContent(output)) { - debug('readThrough:cache-hit', fileName) + logger.debug({ fileName }, 'readThrough(): cache hit') memoryCache.outputs[fileName] = output return output } } catch (err) {} - debug('readThrough:cache-miss', fileName) + logger.debug({ fileName }, 'readThrough(): cache miss') const [value, sourceMap] = compile(code, fileName, lineOffset) const output = updateOutput(value, fileName, sourceMap, getExtension, cwd) - debug('readThrough:write-caches', fileName, 'cache file', outputPath) + logger.debug({ fileName, outputPath }, 'readThrough(): writing caches') memoryCache.outputs[fileName] = output writeFileSync(outputPath, output) diff --git a/src/config/config-set.ts b/src/config/config-set.ts index 3af3a94cb0..52151a73a8 100644 --- a/src/config/config-set.ts +++ b/src/config/config-set.ts @@ -37,6 +37,10 @@ import { normalizeSlashes } from '../util/normalize-slashes' import { createCompiler } from '../compiler' import { version as myVersion } from '..' import semver from 'semver' +import { rootLogger } from '../util/logger' +import { Logger } from 'bs-logger' + +const logger = rootLogger.child({ namespace: 'config' }) interface ReadTsConfigResult { // what we get from reading the config file if any, or inline options @@ -120,10 +124,17 @@ const toDiagnosticCodeList = (items: any, into: number[] = []): number[] => { } export class ConfigSet { + readonly logger: Logger + constructor( private _jestConfig: jest.ProjectConfig, readonly parentOptions?: TsJestGlobalOptions, - ) {} + parentLogger?: Logger, + ) { + this.logger = parentLogger + ? parentLogger.child({ namespace: 'config' }) + : logger + } @Memoize() get jest(): jest.ProjectConfig { @@ -136,6 +147,7 @@ export class ConfigSet { ...globals['ts-jest'], } } + this.logger.debug({ jestConfig: config }, 'normalized jest config') return config } @@ -219,7 +231,7 @@ export class ConfigSet { ) // parsed options - return { + const res: TsJestConfig = { tsConfig, babelConfig, diagnostics, @@ -227,6 +239,8 @@ export class ConfigSet { compiler: options.compiler || 'typescript', stringifyContentPathRegex, } + this.logger.debug({ tsJestConfig: res }, 'normalized ts-jest config') + return res } get typescript(): ParsedCommandLine { @@ -252,6 +266,8 @@ export class ConfigSet { if (configDiagnosticList.length) { throw this.createTsError(configDiagnosticList) } + + this.logger.debug({ tsconfig: result }, 'normalized typescript config') return result } @@ -260,7 +276,10 @@ export class ConfigSet { const { tsJest: { babelConfig }, } = this - if (babelConfig == null) return + if (babelConfig == null) { + this.logger.debug('babel is disabled') + return + } let base: BabelConfig = { cwd: this.cwd } if (babelConfig.kind === 'file') { if (babelConfig.value) { @@ -289,6 +308,7 @@ export class ConfigSet { config = new OptionManager().init(base) as BabelConfig } + this.logger.debug({ babelConfig: config }, 'normalized babel config') return config } @@ -301,6 +321,7 @@ export class ConfigSet { get babelJestTransformer(): BabelJestTransformer | undefined { const { babel } = this if (!babel) return + this.logger.debug('creating babel-jest transformer') return importer .babelJest(ImportReasons.BabelJest) .createTransformer(babel) as BabelJestTransformer @@ -393,7 +414,10 @@ export class ConfigSet { @Memoize() get tsCacheDir(): string | undefined { - if (!this.jest.cache) return + if (!this.jest.cache) { + logger.debug('file caching disabled') + return + } const cacheSufix = sha1( stringify({ version: this.compilerModule.version, @@ -403,7 +427,9 @@ export class ConfigSet { ignoreDiagnostics: this.tsJest.diagnostics.ignoreCodes, }), ) - return join(this.jest.cacheDirectory, `ts-jest-${cacheSufix}`) + const res = join(this.jest.cacheDirectory, `ts-jest-${cacheSufix}`) + logger.debug({ cacheDirectory: res }, `will use file caching`) + return res } get rootDir(): string { @@ -438,6 +464,11 @@ export class ConfigSet { : ts.findConfigFile(normalizeSlashes(this.cwd), ts.sys.fileExists) if (configFileName) { + this.logger.debug( + { tsConfigFileName: configFileName }, + 'readTsConfig(): reading', + configFileName, + ) const result = ts.readConfigFile(configFileName, ts.sys.readFile) // Return diagnostics. @@ -502,6 +533,13 @@ export class ConfigSet { interpolate(Errors.FileNotFound, { inputPath, resolvedPath: path }), ) } + this.logger.debug( + { fromPath: inputPath, toPath: path }, + 'resolved path from', + inputPath, + 'to', + path, + ) return path } diff --git a/src/config/create-jest-preset.ts b/src/config/create-jest-preset.ts index 341f5097e7..e3e5a15b0e 100644 --- a/src/config/create-jest-preset.ts +++ b/src/config/create-jest-preset.ts @@ -1,5 +1,8 @@ import * as jestConfig from 'jest-config' import { CreateJestPresetOptions } from '../types' +import { rootLogger } from '../util/logger' + +const logger = rootLogger.child({ namespace: 'jest-preset' }) // jest 22 doesn't have defaults const defaults = jestConfig.defaults || { @@ -14,6 +17,12 @@ const defaults = jestConfig.defaults || { export function createJestPreset({ allowJs = false, }: CreateJestPresetOptions = {}) { + logger.debug( + { allowJs }, + 'creating jest presets', + allowJs ? 'handling' : 'not handling', + 'JavaScript files', + ) return { transform: { ...defaults.transform, diff --git a/src/index.spec.ts b/src/index.spec.ts index edd0646538..7640bc4600 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -1,5 +1,4 @@ // tslint:disable:max-line-length -import { __setup } from './util/debug' import * as tsJest from '.' import { TsJestTransformer } from './ts-jest-transformer' @@ -47,9 +46,7 @@ describe('old entry point', () => { expect(spy).toHaveBeenCalledTimes(1) expect(spy.mock.calls[0]).toMatchInlineSnapshot(` Array [ - "ts-jest:", - "[deprecated]", - "Replace any occurrences of \\"ts-jest/dist/preprocessor.js\\" or \\"/node_modules/ts-jest/preprocessor.js\\" in the 'transform' section of your Jest config with just \\"ts-jest\\".", + "ts-jest[main] (WARN) Replace any occurrences of \\"ts-jest/dist/preprocessor.js\\" or \\"/node_modules/ts-jest/preprocessor.js\\" in the 'transform' section of your Jest config with just \\"ts-jest\\".", ] `) }) diff --git a/src/transformers/hoisting.ts b/src/transformers/hoisting.ts index 3ea88ff15f..68ff94c17d 100644 --- a/src/transformers/hoisting.ts +++ b/src/transformers/hoisting.ts @@ -11,7 +11,7 @@ import { Transformer, } from 'typescript' import { ConfigSet } from '../config/config-set' -import { wrapWithDebug } from '../util/debug' +import { LogContexts, LogLevels } from 'bs-logger' /** * What methods of `jest` should we hoist @@ -23,6 +23,7 @@ const HOIST_METHODS = ['mock', 'unmock'] * @param cs Current jest configuration-set */ export function factory(cs: ConfigSet) { + const logger = cs.logger.child({ namespace: 'ts-hoisting' }) /** * Our compiler (typescript, or a module with typescript-like interface) */ @@ -122,8 +123,9 @@ export function factory(cs: ConfigSet) { // returns the transformer factory return (ctx: TransformationContext): Transformer => { - return wrapWithDebug( - (sf: SourceFile) => ['customTranformer#hoisting', sf.fileName], + return logger.wrap( + { [LogContexts.logLevel]: LogLevels.debug, call: null }, + 'visitSourceFileNode(): hoisting', (sf: SourceFile) => ts.visitNode(sf, createVisitor(ctx, sf)), ) } diff --git a/src/ts-jest-transformer.ts b/src/ts-jest-transformer.ts index b291e31e61..88c36b5f97 100644 --- a/src/ts-jest-transformer.ts +++ b/src/ts-jest-transformer.ts @@ -4,7 +4,8 @@ import { JsonableValue } from './util/jsonable-value' import { ConfigSet } from './config/config-set' import { stringify, parse } from './util/json' import { inspect } from 'util' -import { debug } from './util/debug' +import { Logger } from 'bs-logger' +import { rootLogger } from './util/logger' /** * @internal @@ -25,6 +26,7 @@ export class TsJestTransformer implements jest.Transformer { return ++TsJestTransformer._lastTransformerId } + readonly logger: Logger readonly id: number readonly options: TsJestGlobalOptions @@ -33,7 +35,11 @@ export class TsJestTransformer implements jest.Transformer { constructor(baseOptions: TsJestGlobalOptions = {}) { this.options = { ...baseOptions } this.id = TsJestTransformer._nextTransformerId - debug('created new transformer', this) + this.logger = rootLogger.child({ + transformerId: this.id, + namespace: 'jest-transformer', + }) + this.logger.debug({ baseOptions }, 'created new transformer') } [INSPECT_CUSTOM]() { @@ -68,7 +74,7 @@ export class TsJestTransformer implements jest.Transformer { } // create the new record in the index - const configSet = new ConfigSet(jestConfigObj, this.options) + const configSet = new ConfigSet(jestConfigObj, this.options, this.logger) this._configSetsIndex.push({ jestConfig: new JsonableValue(jestConfigObj), configSet, @@ -82,6 +88,11 @@ export class TsJestTransformer implements jest.Transformer { jestConfig: jest.ProjectConfig, transformOptions?: jest.TransformOptions, ): jest.TransformedSource | string { + this.logger.debug( + { fileName: filePath, transformOptions }, + 'processing', + filePath, + ) let result: string | jest.TransformedSource let source: string = input @@ -103,11 +114,16 @@ export class TsJestTransformer implements jest.Transformer { // calling babel-jest transformer if (babelJest) { + this.logger.debug({ fileName: filePath }, 'calling babel-jest processor') result = babelJest.process(result, filePath, jestConfig, transformOptions) } // allows hooks (usefull for testing) if (hooks.afterProcess) { + this.logger.debug( + { fileName: filePath, hookName: 'afterProcess' }, + 'calling afterProcess hook', + ) const newResult = hooks.afterProcess( [input, filePath, jestConfig, transformOptions], result, @@ -136,6 +152,11 @@ export class TsJestTransformer implements jest.Transformer { jestConfigStr: string, transformOptions: { instrument?: boolean; rootDir?: string } = {}, ): string { + this.logger.debug( + { fileName: filePath, transformOptions }, + 'computing cache key for', + filePath, + ) const configs = this.configsFor(jestConfigStr) const { instrument = false } = transformOptions return sha1( diff --git a/src/types.ts b/src/types.ts index 72247f3e4f..a40b6fe7d0 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,6 @@ import _ts, { CompilerOptions } from 'typescript' import * as _babel from 'babel__core' +import { Writable } from 'stream' export type TBabelCore = typeof _babel export type TTypeScript = typeof _ts diff --git a/src/util/__mocks__/logger.ts b/src/util/__mocks__/logger.ts new file mode 100644 index 0000000000..406d2fe018 --- /dev/null +++ b/src/util/__mocks__/logger.ts @@ -0,0 +1,3 @@ +import { testing } from 'bs-logger' + +export const rootLogger = testing.createLoggerMock() diff --git a/src/util/__snapshots__/backports.spec.ts.snap b/src/util/__snapshots__/backports.spec.ts.snap index bb0dfbd196..eb5ca9b4de 100644 --- a/src/util/__snapshots__/backports.spec.ts.snap +++ b/src/util/__snapshots__/backports.spec.ts.snap @@ -16,7 +16,10 @@ Object { } `; -exports[`backportJestConfig with "globals.__TRANSFORM_HTML__" set to false should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.__TRANSFORM_HTML__\\" is deprecated, use \\"[jest-config].globals.ts-jest.stringifyContentPathRegex\\" instead."`; +exports[`backportJestConfig with "globals.__TRANSFORM_HTML__" set to false should wran the user 1`] = ` +"[level:40] \\"[jest-config].globals.__TRANSFORM_HTML__\\" is deprecated, use \\"[jest-config].globals.ts-jest.stringifyContentPathRegex\\" instead. +" +`; exports[`backportJestConfig with "globals.__TRANSFORM_HTML__" set to true should have changed the config correctly: before 1`] = ` Object { @@ -36,7 +39,10 @@ Object { } `; -exports[`backportJestConfig with "globals.__TRANSFORM_HTML__" set to true should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.__TRANSFORM_HTML__\\" is deprecated, use \\"[jest-config].globals.ts-jest.stringifyContentPathRegex\\" instead."`; +exports[`backportJestConfig with "globals.__TRANSFORM_HTML__" set to true should wran the user 1`] = ` +"[level:40] \\"[jest-config].globals.__TRANSFORM_HTML__\\" is deprecated, use \\"[jest-config].globals.ts-jest.stringifyContentPathRegex\\" instead. +" +`; exports[`backportJestConfig with "globals.__TS_CONFIG__" set to { foo: 'bar' } should have changed the config correctly: before 1`] = ` Object { @@ -60,7 +66,10 @@ Object { } `; -exports[`backportJestConfig with "globals.__TS_CONFIG__" set to { foo: 'bar' } should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.__TS_CONFIG__\\" is deprecated, use \\"[jest-config].globals.ts-jest.tsConfig\\" instead."`; +exports[`backportJestConfig with "globals.__TS_CONFIG__" set to { foo: 'bar' } should wran the user 1`] = ` +"[level:40] \\"[jest-config].globals.__TS_CONFIG__\\" is deprecated, use \\"[jest-config].globals.ts-jest.tsConfig\\" instead. +" +`; exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to '\\\\.spec\\\\.ts$' should have changed the config correctly: before 1`] = ` Object { @@ -84,7 +93,10 @@ Object { } `; -exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to '\\\\.spec\\\\.ts$' should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.ts-jest.enableTsDiagnostics\\" is deprecated, use \\"[jest-config].globals.ts-jest.diagnostics\\" instead."`; +exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to '\\\\.spec\\\\.ts$' should wran the user 1`] = ` +"[level:40] \\"[jest-config].globals.ts-jest.enableTsDiagnostics\\" is deprecated, use \\"[jest-config].globals.ts-jest.diagnostics\\" instead. +" +`; exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to false should have changed the config correctly: before 1`] = ` Object { @@ -106,7 +118,10 @@ Object { } `; -exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to false should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.ts-jest.enableTsDiagnostics\\" is deprecated, use \\"[jest-config].globals.ts-jest.diagnostics\\" instead."`; +exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to false should wran the user 1`] = ` +"[level:40] \\"[jest-config].globals.ts-jest.enableTsDiagnostics\\" is deprecated, use \\"[jest-config].globals.ts-jest.diagnostics\\" instead. +" +`; exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to true should have changed the config correctly: before 1`] = ` Object { @@ -128,7 +143,10 @@ Object { } `; -exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to true should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.ts-jest.enableTsDiagnostics\\" is deprecated, use \\"[jest-config].globals.ts-jest.diagnostics\\" instead."`; +exports[`backportJestConfig with "globals.ts-jest.enableTsDiagnostics" set to true should wran the user 1`] = ` +"[level:40] \\"[jest-config].globals.ts-jest.enableTsDiagnostics\\" is deprecated, use \\"[jest-config].globals.ts-jest.diagnostics\\" instead. +" +`; exports[`backportJestConfig with "globals.ts-jest.skipBabel" set to false should have changed the config correctly: before 1`] = ` Object { @@ -150,7 +168,10 @@ Object { } `; -exports[`backportJestConfig with "globals.ts-jest.skipBabel" set to false should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.ts-jest.skipBabel\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead."`; +exports[`backportJestConfig with "globals.ts-jest.skipBabel" set to false should wran the user 1`] = ` +"[level:40] \\"[jest-config].globals.ts-jest.skipBabel\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead. +" +`; exports[`backportJestConfig with "globals.ts-jest.skipBabel" set to true should have changed the config correctly: before 1`] = ` Object { @@ -170,7 +191,10 @@ Object { } `; -exports[`backportJestConfig with "globals.ts-jest.skipBabel" set to true should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.ts-jest.skipBabel\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead."`; +exports[`backportJestConfig with "globals.ts-jest.skipBabel" set to true should wran the user 1`] = ` +"[level:40] \\"[jest-config].globals.ts-jest.skipBabel\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead. +" +`; exports[`backportJestConfig with "globals.ts-jest.tsConfigFile" set to 'tsconfig.build.json' should have changed the config correctly: before 1`] = ` Object { @@ -192,7 +216,10 @@ Object { } `; -exports[`backportJestConfig with "globals.ts-jest.tsConfigFile" set to 'tsconfig.build.json' should wran the user 1`] = `"warn ts-jest: \\"[jest-config].globals.ts-jest.tsConfigFile\\" is deprecated, use \\"[jest-config].globals.ts-jest.tsConfig\\" instead."`; +exports[`backportJestConfig with "globals.ts-jest.tsConfigFile" set to 'tsconfig.build.json' should wran the user 1`] = ` +"[level:40] \\"[jest-config].globals.ts-jest.tsConfigFile\\" is deprecated, use \\"[jest-config].globals.ts-jest.tsConfig\\" instead. +" +`; exports[`backportJestConfig with "globals.ts-jest.useBabelrc" set to false should have changed the config correctly: before 1`] = ` Object { @@ -215,8 +242,9 @@ Object { `; exports[`backportJestConfig with "globals.ts-jest.useBabelrc" set to false should wran the user 1`] = ` -"warn ts-jest: \\"[jest-config].globals.ts-jest.useBabelrc\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead. - ↳ See \`babel-jest\` related issue: https://github.com/facebook/jest/issues/3845" +"[level:40] \\"[jest-config].globals.ts-jest.useBabelrc\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead. + ↳ See \`babel-jest\` related issue: https://github.com/facebook/jest/issues/3845 +" `; exports[`backportJestConfig with "globals.ts-jest.useBabelrc" set to true should have changed the config correctly: before 1`] = ` @@ -240,6 +268,7 @@ Object { `; exports[`backportJestConfig with "globals.ts-jest.useBabelrc" set to true should wran the user 1`] = ` -"warn ts-jest: \\"[jest-config].globals.ts-jest.useBabelrc\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead. - ↳ See \`babel-jest\` related issue: https://github.com/facebook/jest/issues/3845" +"[level:40] \\"[jest-config].globals.ts-jest.useBabelrc\\" is deprecated, use \\"[jest-config].globals.ts-jest.babelConfig\\" instead. + ↳ See \`babel-jest\` related issue: https://github.com/facebook/jest/issues/3845 +" `; diff --git a/src/util/backports.spec.ts b/src/util/backports.spec.ts index 71ad5b2508..5d4785a71c 100644 --- a/src/util/backports.spec.ts +++ b/src/util/backports.spec.ts @@ -1,12 +1,12 @@ import { backportJestConfig } from './backports' import set from 'lodash.set' import { inspect } from 'util' -import { __setup } from './debug' +import { logTargetMock } from '../__helpers__/mocks' + +const logTarget = logTargetMock() -const logger = jest.fn() -__setup({ logger }) beforeEach(() => { - logger.mockClear() + logTarget.clear() }) describe('backportJestConfig', () => { @@ -20,8 +20,7 @@ describe('backportJestConfig', () => { describe(`with "${oldPath}" set to ${inspect(val)}`, () => { it(`should wran the user`, () => { backportJestConfig(original) - expect(logger).toHaveBeenCalledTimes(1) - expect(logger.mock.calls[0].join(' ')).toMatchSnapshot() + expect(logTarget.lines.warn.last).toMatchSnapshot() }) // should warn the user it(`should have changed the config correctly`, () => { expect(original).toMatchSnapshot('before') diff --git a/src/util/backports.ts b/src/util/backports.ts index 17e4c891d8..d67001633c 100644 --- a/src/util/backports.ts +++ b/src/util/backports.ts @@ -1,111 +1,140 @@ import { interpolate, Deprecateds } from './messages' -import { warn, wrapWithDebug } from './debug' +import { Logger } from 'bs-logger' -export const backportJestConfig = wrapWithDebug( - 'backportJestConfig', - function backportJestConfig< - T extends jest.InitialOptions | jest.ProjectConfig - >(config: T = {} as any, silent = false): T { - const { globals = {} } = config as any - const { 'ts-jest': tsJest = {} } = globals as any - const mergeTsJest: any = {} - const warnConfig = silent - ? () => undefined - : (oldPath: string, newPath: string, note?: string) => { - warn( - interpolate( - note - ? Deprecateds.ConfigOptionWithNote - : Deprecateds.ConfigOption, - { - oldPath, - newPath, - note, - }, - ), - ) - } +// we must use a getter here since the root logger is using ourself +let _logger: Logger +const logger = { + get get() { + return ( + _logger || + (_logger = require('./logger').rootLogger.child({ + namespace: 'backports', + })) + ) + }, +} + +export const backportJestConfig = < + T extends jest.InitialOptions | jest.ProjectConfig +>( + config: T = {} as any, +): T => { + logger.get.debug({ config }, 'backporting config') + + const { globals = {} } = config as any + const { 'ts-jest': tsJest = {} } = globals as any + const mergeTsJest: any = {} + const warnConfig = (oldPath: string, newPath: string, note?: string) => { + logger.get.warn( + interpolate( + note ? Deprecateds.ConfigOptionWithNote : Deprecateds.ConfigOption, + { + oldPath, + newPath, + note, + }, + ), + ) + } - if ('__TS_CONFIG__' in globals) { - warnConfig('globals.__TS_CONFIG__', 'globals.ts-jest.tsConfig') - if (typeof globals.__TS_CONFIG__ === 'object') { - mergeTsJest.tsConfig = globals.__TS_CONFIG__ - } - delete globals.__TS_CONFIG__ + if ('__TS_CONFIG__' in globals) { + warnConfig('globals.__TS_CONFIG__', 'globals.ts-jest.tsConfig') + if (typeof globals.__TS_CONFIG__ === 'object') { + mergeTsJest.tsConfig = globals.__TS_CONFIG__ } + delete globals.__TS_CONFIG__ + } - if ('__TRANSFORM_HTML__' in globals) { - warnConfig( - 'globals.__TRANSFORM_HTML__', - 'globals.ts-jest.stringifyContentPathRegex', - ) - if (globals.__TRANSFORM_HTML__) { - mergeTsJest.stringifyContentPathRegex = '\\.html?$' - } - delete globals.__TRANSFORM_HTML__ + if ('__TRANSFORM_HTML__' in globals) { + warnConfig( + 'globals.__TRANSFORM_HTML__', + 'globals.ts-jest.stringifyContentPathRegex', + ) + if (globals.__TRANSFORM_HTML__) { + mergeTsJest.stringifyContentPathRegex = '\\.html?$' } + delete globals.__TRANSFORM_HTML__ + } - if ('tsConfigFile' in tsJest) { - warnConfig('globals.ts-jest.tsConfigFile', 'globals.ts-jest.tsConfig') - if (tsJest.tsConfigFile) { - mergeTsJest.tsConfig = tsJest.tsConfigFile - } - delete tsJest.tsConfigFile + if ('tsConfigFile' in tsJest) { + warnConfig('globals.ts-jest.tsConfigFile', 'globals.ts-jest.tsConfig') + if (tsJest.tsConfigFile) { + mergeTsJest.tsConfig = tsJest.tsConfigFile } + delete tsJest.tsConfigFile + } - if ('enableTsDiagnostics' in tsJest) { - warnConfig( - 'globals.ts-jest.enableTsDiagnostics', - 'globals.ts-jest.diagnostics', - ) - if (tsJest.enableTsDiagnostics) { - mergeTsJest.diagnostics = - typeof tsJest.enableTsDiagnostics === 'string' - ? { pathRegex: tsJest.enableTsDiagnostics } - : true - } else { - mergeTsJest.diagnostics = false - } - delete tsJest.enableTsDiagnostics + if ('enableTsDiagnostics' in tsJest) { + warnConfig( + 'globals.ts-jest.enableTsDiagnostics', + 'globals.ts-jest.diagnostics', + ) + if (tsJest.enableTsDiagnostics) { + mergeTsJest.diagnostics = + typeof tsJest.enableTsDiagnostics === 'string' + ? { pathRegex: tsJest.enableTsDiagnostics } + : true + } else { + mergeTsJest.diagnostics = false } + delete tsJest.enableTsDiagnostics + } - if ('useBabelrc' in tsJest) { - warnConfig( - 'globals.ts-jest.useBabelrc', - 'globals.ts-jest.babelConfig', - Deprecateds.ConfigOptionUseBabelRcNote, - ) - if (tsJest.useBabelrc != null) { - mergeTsJest.babelConfig = tsJest.useBabelrc ? true : {} - } - delete tsJest.useBabelrc + if ('useBabelrc' in tsJest) { + warnConfig( + 'globals.ts-jest.useBabelrc', + 'globals.ts-jest.babelConfig', + Deprecateds.ConfigOptionUseBabelRcNote, + ) + if (tsJest.useBabelrc != null) { + mergeTsJest.babelConfig = tsJest.useBabelrc ? true : {} } + delete tsJest.useBabelrc + } - // if ('babelConfig' in tsJest) { - // warnConfig('globals.ts-jest.babelConfig', 'globals.ts-jest.babelConfig') - // if (tsJest.babelConfig != null) { - // mergeTsJest.babelConfig = tsJest.babelConfig - // } - // delete tsJest.babelConfig - // } + // if ('babelConfig' in tsJest) { + // warnConfig('globals.ts-jest.babelConfig', 'globals.ts-jest.babelConfig') + // if (tsJest.babelConfig != null) { + // mergeTsJest.babelConfig = tsJest.babelConfig + // } + // delete tsJest.babelConfig + // } - if ('skipBabel' in tsJest) { - warnConfig('globals.ts-jest.skipBabel', 'globals.ts-jest.babelConfig') - if (tsJest.skipBabel === false && !mergeTsJest.babelConfig) { - mergeTsJest.babelConfig = true - } - delete tsJest.skipBabel + if ('skipBabel' in tsJest) { + warnConfig('globals.ts-jest.skipBabel', 'globals.ts-jest.babelConfig') + if (tsJest.skipBabel === false && !mergeTsJest.babelConfig) { + mergeTsJest.babelConfig = true } + delete tsJest.skipBabel + } - return { - ...(config as any), - globals: { - ...globals, - 'ts-jest': { - ...mergeTsJest, - ...tsJest, - }, + return { + ...(config as any), + globals: { + ...globals, + 'ts-jest': { + ...mergeTsJest, + ...tsJest, }, + }, + } +} + +export const backportTsJestDebugEnvVar = () => { + if ('TS_JEST_DEBUG' in process.env) { + const shouldLog = !/^\s*(?:0|f(?:alse)?|no?|disabled?|off|)\s*$/i.test( + process.env.TS_JEST_DEBUG || '', + ) + delete process.env.TS_JEST_DEBUG + if (shouldLog) { + process.env.TS_JEST_LOG = `ts-jest.log,stderr:warn` } - }, -) + // must be called after because this function is used when the root logger is created + logger.get.warn( + interpolate(Deprecateds.EnvVar, { + old: 'TS_JEST_DEBUG', + new: 'TS_JEST_LOG', + }), + ) + } +} diff --git a/src/util/debug.spec.ts b/src/util/debug.spec.ts deleted file mode 100644 index 1b53cda4fb..0000000000 --- a/src/util/debug.spec.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { debug, wrapWithDebug, __setup, warn } from './debug' - -const stdoutSpy = jest.spyOn(process.stdout, 'write') -const stderrSpy = jest.spyOn(process.stderr, 'write') - -const reset = () => __setup({ logFile: false }) - -let oldState: any -beforeEach(() => { - oldState = process.env.TS_JEST_DEBUG - delete process.env.TS_JEST_DEBUG - stderrSpy.mockReset() - stdoutSpy.mockReset() - stdoutSpy.mockImplementation(() => undefined) - stderrSpy.mockImplementation(() => undefined) -}) -afterEach(() => { - process.env.TS_JEST_DEBUG = oldState -}) -afterAll(() => { - stderrSpy.mockRestore() - stdoutSpy.mockRestore() -}) - -describe('debug', () => { - it('should log to stdout when TS_JEST_DEBUG is truthy', () => { - process.env.TS_JEST_DEBUG = '1' - reset() - debug('foo') - expect(stdoutSpy).toHaveBeenCalledTimes(1) - expect(stdoutSpy.mock.calls[0][0]).toBe('ts-jest: foo\n') - }) - it('should NOT log to stdout when TS_JEST_DEBUG is falsy', () => { - process.env.TS_JEST_DEBUG = '' - reset() - debug('foo') - expect(stdoutSpy).not.toHaveBeenCalled() - }) - it('should NOT log to stdout when TS_JEST_DEBUG is not set', () => { - delete process.env.TS_JEST_DEBUG - reset() - debug('foo') - expect(stdoutSpy).not.toHaveBeenCalled() - }) -}) -describe('warn', () => { - it('should log to stderr when TS_JEST_DEBUG is truthy', () => { - process.env.TS_JEST_DEBUG = '1' - reset() - warn('foo') - expect(stderrSpy).toHaveBeenCalledTimes(1) - expect(stderrSpy.mock.calls[0][0]).toBe('ts-jest: foo\n') - }) - it('should log to stderr even when TS_JEST_DEBUG is falsy', () => { - delete process.env.TS_JEST_DEBUG - reset() - warn('foo') - expect(stderrSpy).toHaveBeenCalledTimes(1) - expect(stderrSpy.mock.calls[0][0]).toBe('ts-jest: foo\n') - }) -}) - -describe('wrapWithDebug', () => { - const subject = (val: string) => `hello ${val}` - const wrapAndCall = (val: string) => wrapWithDebug('foo', subject)(val) - - it('should log to stdout when TS_JEST_DEBUG is truthy', () => { - process.env.TS_JEST_DEBUG = '1' - reset() - expect(wrapAndCall('bar')).toBe('hello bar') - expect(stdoutSpy).toHaveBeenCalledTimes(1) - expect(stdoutSpy.mock.calls[0][0]).toBe('ts-jest: foo\n') - }) - it('should NOT log to stdout when TS_JEST_DEBUG is falsy', () => { - process.env.TS_JEST_DEBUG = '' - reset() - expect(wrapAndCall('bar')).toBe('hello bar') - expect(stdoutSpy).not.toHaveBeenCalled() - }) - it('should NOT log to stdout when TS_JEST_DEBUG is not set', () => { - delete process.env.TS_JEST_DEBUG - reset() - expect(wrapAndCall('bar')).toBe('hello bar') - expect(stdoutSpy).not.toHaveBeenCalled() - }) -}) diff --git a/src/util/debug.ts b/src/util/debug.ts deleted file mode 100644 index 4bba5ddf85..0000000000 --- a/src/util/debug.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { format } from 'util' -import { resolve } from 'path' -import { appendFileSync } from 'fs' - -export let DEBUG_MODE!: boolean - -export let debug!: typeof console.log -export let warn!: typeof console.warn - -export let wrapWithDebug!: any>( - msg: string | string[] | ((...args: any[]) => string | string[]), - func: T, -) => T - -type LogKind = 'log' | 'warn' -type Logger = (kind: LogKind, ...args: any[]) => void - -export let LOG_PREFIX = 'ts-jest:' - -export const defaultLogger: Logger = ( - kind: LogKind, - msg: string = '', - ...args: any[] -) => { - // we use stderr/stdout dirrectly so that the log won't be swallowed by jest - // the dummy calback is to ensure output on CI with node 6 - if (kind === 'warn') { - process.stderr.write(format(msg, ...args) + '\n', () => undefined) - } else if (kind) { - process.stdout.write(format(msg, ...args) + '\n', () => undefined) - } -} - -let writeLogToFile: string | undefined -const markedLogFiles: { [path: string]: 0 } = Object.create(null) - -const time = () => new Date().toISOString() -const arrify = ( - input: string | string[] | ((...a: any[]) => string | string[]), - args: any[], -) => { - const strOrArray = typeof input === 'function' ? input(...args) : input - return Array.isArray(strOrArray) ? strOrArray : [strOrArray] -} - -interface SetupOptions { - enabled?: boolean - logger?: Logger - prefix?: string - logFile?: string | false -} -export function __setup({ - logger = defaultLogger, - logFile = process.env.TS_JEST_DEBUG || process.env.TS_JEST_DEBUG_FILE - ? resolve( - process.cwd(), - process.env.TS_JEST_DEBUG_FILE || 'ts-jest-debug.log', - ) - : undefined, - enabled = !!process.env.TS_JEST_DEBUG || logger !== defaultLogger, - prefix = 'ts-jest:', -}: SetupOptions = {}) { - writeLogToFile = logFile || undefined - DEBUG_MODE = enabled - LOG_PREFIX = prefix - - // wrap logger so that we write to file as well - if (writeLogToFile) { - logger = (old => (kind: LogKind, ...args: [any, ...any[]]) => { - const prefix = `[${time()}][${kind}]` - const message = format(...args) - appendFileSync( - writeLogToFile as string, - `${prefix} ${message.replace(/\n/g, '\\n')}\n`, - 'utf8', - ) - // call the original logger only if debug enabled - if (enabled) old(kind, ...args) - })(logger) - } - - // log debug - debug = - DEBUG_MODE || writeLogToFile - ? (...args: any[]) => logger('log', LOG_PREFIX, ...args) - : () => undefined - - // log warning - warn = (...args: any[]) => logger('warn', LOG_PREFIX, ...args) - - // function wrapper - wrapWithDebug = - DEBUG_MODE || writeLogToFile - ? (msg, func) => - function wrapper(this: any) { - logger('log', LOG_PREFIX, ...arrify(msg, [...arguments])) - return func.apply(this, arguments) - } as any - : (_, func) => func - - // mark log file - if (writeLogToFile && !(writeLogToFile in markedLogFiles)) { - markedLogFiles[writeLogToFile] = 0 - debug('initiailized') - } -} - -__setup() diff --git a/src/util/exit-handler.ts b/src/util/exit-handler.ts deleted file mode 100644 index 716ad25fe0..0000000000 --- a/src/util/exit-handler.ts +++ /dev/null @@ -1,53 +0,0 @@ -export interface OnExitHandlerOptions { - cleanExit: boolean - exitCode?: number - signal?: string - error?: Error -} - -interface InternalExitHandlerOptions { - exitCode?: number - cleanExit?: boolean - signal?: string - error?: Error - exitWithCode?: number -} - -let installed: boolean = false -/** - * @see https://stackoverflow.com/a/14032965/1603618 - * @param callback Called when the program exists - */ -export function install(callback: (opt: OnExitHandlerOptions) => void) { - if (installed) throw new Error(`On exit already installed.`) - installed = true - - function exitHandler({ - exitCode, - error, - signal, - cleanExit = false, - exitWithCode, - }: InternalExitHandlerOptions = {}) { - try { - callback({ error, exitCode, cleanExit, signal }) - } catch (err) {} - if (exitWithCode) { - process.exit(exitCode) - } - } - - // do something when app is closing - process.on('exit', exitCode => exitHandler({ exitCode, cleanExit: true })) - // catches ctrl+c event - process.on('SIGINT', () => exitHandler({ signal: 'SIGINT', exitWithCode: 1 })) - // catches "kill pid" (for example: nodemon restart) - process.on('SIGUSR1', () => - exitHandler({ signal: 'SIGUSR1', exitWithCode: 1 }), - ) - process.on('SIGUSR2', () => - exitHandler({ signal: 'SIGUSR2', exitWithCode: 1 }), - ) - // catches uncaught exceptions - process.on('uncaughtException', error => exitHandler({ error })) -} diff --git a/src/util/hacks.ts b/src/util/hacks.ts index 83c38851d0..48bd803551 100644 --- a/src/util/hacks.ts +++ b/src/util/hacks.ts @@ -1,5 +1,8 @@ import { TBabelCore, ModulePatcher, BabelConfig } from '../types' import semver from 'semver' +import { rootLogger } from './logger' + +const logger = rootLogger.child({ namespace: 'hacks' }) // tslint:disable-next-line:variable-name export const patchBabelCore_githubIssue6577: ModulePatcher< @@ -16,7 +19,7 @@ export const patchBabelCore_githubIssue6577: ModulePatcher< try { const File = require('babel-core/lib/transformation/file').File File.prototype.initOptions = (original => { - return function(this: any, opt: BabelConfig) { + return function initOptions(this: any, opt: BabelConfig) { const before = opt.sourceMaps const result = original.apply(this, arguments) if (before && before !== result.sourceMaps) { @@ -25,6 +28,7 @@ export const patchBabelCore_githubIssue6577: ModulePatcher< return result } })(File.prototype.initOptions) + logger.info('patched babel-core/lib/transformation/file') } catch (err) {} } return babel diff --git a/src/util/importer.ts b/src/util/importer.ts index 8bdbabc247..f04d8cc6f0 100644 --- a/src/util/importer.ts +++ b/src/util/importer.ts @@ -9,7 +9,9 @@ import { import * as hacks from './hacks' import { ImportReasons, Errors, interpolate, Helps } from './messages' import { VersionCheckers } from './version-checkers' -import { debug } from './debug' +import { rootLogger } from './logger' + +const logger = rootLogger.child({ namespace: 'Importer' }) // When ading an optional dependency which has another reason, add the reason in ImportReasons, and // create a new method in Importer. Thus uses the importer.yourMethod(ImportReasons.TheReason) @@ -29,7 +31,7 @@ const passThru = (action: () => void) => (input: any) => { export class Importer implements TsJestImporter { @Memoize() static get instance() { - debug('Importer.instance', 'creating Importer singleton') + logger.debug('creating Importer singleton') // here we can define patches to apply to modules. // it could be fixes that are not deployed, or // abstractions so that multiple versions work the same @@ -83,10 +85,10 @@ export class Importer implements TsJestImporter { while ((name = tries.shift() as string) !== undefined) { try { loaded = requireModule(name) - debug('Importer#tryThese', 'loaded module', name) + logger.debug('loaded module', name) break } catch (err) { - debug('Importer#tryThese', 'fail loading module', name) + logger.debug('fail loading module', name) } } @@ -96,7 +98,7 @@ export class Importer implements TsJestImporter { @Memoize(name => name) protected _patch(name: string, unpatched: T): T { if (name in this._patches) { - debug('Importer#_patch', 'patching', name) + logger.debug('patching', name) return this._patches[name].reduce( (mod, patcher) => patcher(mod), unpatched, diff --git a/src/util/logger.ts b/src/util/logger.ts new file mode 100644 index 0000000000..e5c6969984 --- /dev/null +++ b/src/util/logger.ts @@ -0,0 +1,12 @@ +import { createLogger, LogContexts, LogLevels } from 'bs-logger' +import { backportTsJestDebugEnvVar } from './backports' + +backportTsJestDebugEnvVar() + +export const rootLogger = createLogger({ + context: { + [LogContexts.package]: 'ts-jest', + [LogContexts.logLevel]: LogLevels.trace, + }, + targets: process.env.TS_JEST_LOG || undefined, +}) diff --git a/src/util/messages.ts b/src/util/messages.ts index 0fa0216191..cb3af9a7cc 100644 --- a/src/util/messages.ts +++ b/src/util/messages.ts @@ -16,6 +16,7 @@ export enum Helps { } export enum Deprecateds { + EnvVar = 'Using env. var "{{old}}" is deprecated, use "{{new}}" instead.', ConfigOption = '"[jest-config].{{oldPath}}" is deprecated, use "[jest-config].{{newPath}}" instead.', ConfigOptionWithNote = '"[jest-config].{{oldPath}}" is deprecated, use "[jest-config].{{newPath}}" instead.\n ↳ {{note}}', ConfigOptionUseBabelRcNote = 'See `babel-jest` related issue: https://github.com/facebook/jest/issues/3845', diff --git a/src/util/ts-error.ts b/src/util/ts-error.ts index c84f7e58da..110aa5690a 100644 --- a/src/util/ts-error.ts +++ b/src/util/ts-error.ts @@ -1,7 +1,9 @@ import { inspect } from 'util' import { BaseError } from 'make-error' import { Helps, Errors, interpolate } from './messages' -import { debug } from './debug' +import { rootLogger } from './logger' + +const logger = rootLogger.child({ namespace: 'TSError' }) /** * @internal @@ -21,7 +23,7 @@ export class TSError extends BaseError { help: Helps.IgnoreDiagnosticCode, }), ) - debug('TSError#constructor', diagnosticCodes, diagnosticText) + logger.debug({ diagnosticCodes, diagnosticText }, 'created new TSError') // ensure we blacklist any of our code Object.defineProperty(this, 'stack', { value: '' }) } diff --git a/src/util/version-checkers.spec.ts b/src/util/version-checkers.spec.ts index db0dbfe570..dee0617b8b 100644 --- a/src/util/version-checkers.spec.ts +++ b/src/util/version-checkers.spec.ts @@ -1,11 +1,13 @@ // tslint:disable:max-line-length -import { __setup } from './debug' import * as _pv from './get-package-version' import { VersionCheckers, VersionChecker } from './version-checkers' -import { mocked } from '../__helpers__/mocks' +import { mocked, logTargetMock } from '../__helpers__/mocks' -const logger = jest.fn() -__setup({ logger }) +const logTarget = logTargetMock() + +beforeEach(() => { + logTarget.clear() +}) jest.mock('./get-package-version') @@ -50,7 +52,6 @@ function describeChecker( ) { describe(moduleName, () => { beforeEach(() => { - logger.mockClear() checker.forget() }) @@ -64,9 +65,9 @@ function describeChecker( it(`should log with warn()`, () => { checker.warn() - const warnings = logger.mock.calls.filter(args => args[0] === 'warn') + const warnings = logTarget.messages.warn expect(warnings).toHaveLength(1) - expect(warnings[0][2]).toMatch( + expect(warnings[0].message).toMatch( testVersion ? 'has not been tested with ts-jest' : 'is not installed', @@ -75,11 +76,7 @@ function describeChecker( it(`should log only once with warn()`, () => { checker.warn() checker.warn() - expect( - logger.mock.calls - .map(args => args[0]) - .filter(lvl => lvl === 'warn'), - ).toHaveLength(1) + expect(logTarget.messages.warn).toHaveLength(1) }) it(`should throw with raise()`, () => { expect(checker.raise).toThrow() @@ -98,7 +95,7 @@ function describeChecker( }) it(`should not log with warn()`, () => { checker.warn() - expect(logger.mock.calls.map(args => args[0])).not.toContain('warn') + expect(logTarget.messages.warn).toHaveLength(0) }) it(`should not throw with raise()`, () => { expect(checker.raise).not.toThrow() diff --git a/src/util/version-checkers.ts b/src/util/version-checkers.ts index 9c95fef151..d7838d059a 100644 --- a/src/util/version-checkers.ts +++ b/src/util/version-checkers.ts @@ -1,7 +1,9 @@ import { satisfies, Range } from 'semver' -import { warn, debug } from './debug' import { interpolate, Errors } from './messages' import { getPackageVersion } from './get-package-version' +import { rootLogger } from './logger' + +const logger = rootLogger.child({ namespace: 'versions' }) export enum ExpectedVersions { Jest = '>=22 <24', @@ -48,10 +50,15 @@ function checkVersion( ): boolean | never { const version = getPackageVersion(name) const success = !!version && satisfies(version, expectedRange) - debug('checkVersion', name, success ? 'OK' : 'NOT OK', { - actual: version, - expected: expectedRange, - }) + logger.debug( + { + actualVersion: version, + expectedVersion: expectedRange, + }, + 'checking version of %s: %s', + name, + success ? 'OK' : 'NOT OK', + ) if (!action || success) return success const message = interpolate( @@ -63,8 +70,9 @@ function checkVersion( }, ) if (action === 'warn') { - warn(message) + logger.warn(message) } else if (action === 'throw') { + logger.fatal(message) throw new RangeError(message) } return success diff --git a/tsconfig.json b/tsconfig.json index 592261a885..4fb4a7d3d6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,10 +1,12 @@ { "compilerOptions": { - "sourceMap": false, - "inlineSourceMap": true, "declaration": true, "downlevelIteration": true, - "target": "es5", + "esModuleInterop": true, + "experimentalDecorators": true, + "importHelpers": true, + "inlineSourceMap": true, + "lib": ["es2015", "es2016.array.include"], "module": "commonjs", "moduleResolution": "node", "noEmitOnError": true, @@ -12,12 +14,11 @@ "noImplicitAny": true, "noImplicitReturns": true, "removeComments": true, - "strict": true, - "experimentalDecorators": true, - "esModuleInterop": true, - "skipLibCheck": true, "resolveJsonModule": true, - "lib": ["es2015", "es2016.array.include"], + "skipLibCheck": true, + "sourceMap": false, + "strict": true, + "target": "es5", "types": ["jest", "node"], }, "include": [