From e46caae881ed1a30f8ed2dede823c876f4b4403e Mon Sep 17 00:00:00 2001 From: Huafu Gandon Date: Thu, 19 Jul 2018 15:33:33 +0200 Subject: [PATCH] fix: big refactor + fixes (mainly cache key + coverage) --- index.d.ts | 11 ---- index.js | 15 ------ package.json | 12 ++--- preprocessor.js | 1 - scripts/tests.js | 10 ---- src/index.ts | 35 +++++++++++++ src/postprocess.ts | 35 +++++++------ src/{preprocessor.ts => preprocess.ts} | 43 +++------------- src/transpile-if-ts.ts | 23 --------- src/transpiler.ts | 5 +- src/{jest-types.ts => types.ts} | 38 ++++++-------- src/utils/constants.ts | 12 +++++ src/utils/get-babel-rc.ts | 50 +++++++++++++++++++ src/utils/get-cache-key.ts | 31 ++++++++++++ src/{utils.ts => utils/index.ts} | 14 +++--- src/{ => utils}/logger.ts | 0 tests/__tests__/get-cache-key.spec.ts | 11 ++-- tests/__tests__/transpiler.spec.ts | 21 ++++++-- tests/coverage-simple/.gitignore | 1 + tests/coverage-simple/Hello.ts | 28 +++++++++++ tests/coverage-simple/NullCoverage.js | 6 +++ tests/coverage-simple/__tests__/Hello.test.ts | 9 ++++ tests/coverage-simple/package.json | 22 ++++++++ tests/coverage-simple/tsconfig.json | 10 ++++ tests/coverage-simple/yarn.lock | 4 ++ tsconfig.build.json | 11 ++++ tsconfig.json | 7 +-- 27 files changed, 299 insertions(+), 166 deletions(-) delete mode 100644 index.d.ts delete mode 100644 index.js delete mode 100644 preprocessor.js create mode 100644 src/index.ts rename src/{preprocessor.ts => preprocess.ts} (65%) delete mode 100644 src/transpile-if-ts.ts rename src/{jest-types.ts => types.ts} (65%) create mode 100644 src/utils/constants.ts create mode 100644 src/utils/get-babel-rc.ts create mode 100644 src/utils/get-cache-key.ts rename src/{utils.ts => utils/index.ts} (94%) rename src/{ => utils}/logger.ts (100%) create mode 100644 tests/coverage-simple/.gitignore create mode 100644 tests/coverage-simple/Hello.ts create mode 100644 tests/coverage-simple/NullCoverage.js create mode 100644 tests/coverage-simple/__tests__/Hello.test.ts create mode 100644 tests/coverage-simple/package.json create mode 100644 tests/coverage-simple/tsconfig.json create mode 100644 tests/coverage-simple/yarn.lock create mode 100644 tsconfig.build.json diff --git a/index.d.ts b/index.d.ts deleted file mode 100644 index 206d91423f..0000000000 --- a/index.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import * as _install from './install'; -import * as preprocessor from './preprocessor'; - -interface TsJestModule { - install: typeof _install.install; - process: typeof preprocessor.process; - getCacheKey: typeof preprocessor.getCacheKey; -} - -declare const tsJestModule: TsJestModule; -export = tsJestModule; diff --git a/index.js b/index.js deleted file mode 100644 index 13ad594168..0000000000 --- a/index.js +++ /dev/null @@ -1,15 +0,0 @@ -// Avoid require()'ing the preprocessor when index.js gets loaded as part -// of the transpiled test file output, to avoid tripping this bug in -// babel-core: https://github.com/babel/babel/pull/6524 which is to be -// fixed in babel-core 7.0. -// Related ts-jest issue: https://github.com/kulshekhar/ts-jest/issues/367 -function lazyRequire(fnName) { - return function() { - return require('./dist/preprocessor')[fnName].apply(null, arguments); - }; -} - -module.exports = { - getCacheKey: lazyRequire('getCacheKey'), - process: lazyRequire('process'), -}; diff --git a/package.json b/package.json index a6abcd5519..501a3327ef 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,18 @@ { "name": "ts-jest", "version": "23.0.1", - "main": "index.js", + "main": "dist/index.js", "types": "./dist/index.d.ts", "description": "A preprocessor with sourcemap support to help use Typescript with Jest", "scripts": { - "build": "cpx index.d.ts dist/ && tsc -p .", - "build:watch": "cpx index.d.ts dist/ && tsc -p . -w", + "build": "tsc -p tsconfig.build.json", + "build:watch": "tsc -p tsconfig.build.json -w", "test:nolint": "npm run clean-build && node scripts/tests.js", - "clean": "rimraf dist/**/* && rimraf tests/simple/coverage && rimraf tests/simple-async/coverage && rimraf tests/**/*/debug.txt && rimraf tests/**/node_modules", + "clean": "rimraf dist/**/* && rimraf tests/*/coverage && rimraf tests/*/debug.txt && rimraf tests/*/node_modules", "clean-build": "npm run clean && npm run build", "pretest": "npm run tslint && npm run clean-build", "test": "node scripts/tests.js", - "tslint": "tslint src/*.ts", + "tslint": "tslint src/**/*.ts", "doc": "doctoc .", "prepublish": "npm run clean-build", "precommit": "lint-staged", @@ -38,7 +38,7 @@ "homepage": "https://github.com/kulshekhar/ts-jest#readme", "jest": { "transform": { - "^.+\\.tsx?$": "/dist/preprocessor.js" + "^.+\\.tsx?$": "/dist/index.js" }, "testRegex": "tests/__tests__/.*\\.spec\\.ts$", "testPathIgnorePatterns": [ diff --git a/preprocessor.js b/preprocessor.js deleted file mode 100644 index d56eb74241..0000000000 --- a/preprocessor.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./dist/preprocessor'); \ No newline at end of file diff --git a/scripts/tests.js b/scripts/tests.js index 3baec1dd28..36934fae5d 100644 --- a/scripts/tests.js +++ b/scripts/tests.js @@ -25,16 +25,6 @@ function createIntegrationMock() { const rootDir = path.resolve('.'); const testCaseModuleFolder = path.join(testCaseNodeModules, 'ts-jest'); - // Copy javascript files - fs.copySync( - path.resolve(rootDir, 'index.js'), - path.resolve(testCaseModuleFolder, 'index.js') - ); - fs.copySync( - path.resolve(rootDir, 'preprocessor.js'), - path.resolve(testCaseModuleFolder, 'preprocessor.js') - ); - // Copy package.json fs.copySync( path.resolve(rootDir, 'package.json'), diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000000..c49fd4fb34 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,35 @@ +// structure of this file heavilly inspired on: +// https://github.com/facebook/jest/blob/master/packages/babel-jest/src/index.js + +import jestPreset from 'babel-preset-jest'; +import getCacheKeyForArgs from './utils/get-cache-key'; +import { TsJestContext, JestCacheKeyArguments } from './types'; +import preprocess from './preprocess'; + +const createTransformer = (options?: any): jest.Transformer => { + const cache = Object.create(null); + + options = Object.assign({}, options, { + compact: false, + plugins: (options && options.plugins) || [], + presets: ((options && options.presets) || []).concat([jestPreset]), + sourceMaps: 'both', + }); + delete options.cacheDirectory; + delete options.filename; + + const context: TsJestContext = { cache, options }; + + const getCacheKey = (...args: any[]) => + getCacheKeyForArgs(args as JestCacheKeyArguments, context); + + return { + canInstrument: true, + getCacheKey, + process: preprocess, + createTransformer: undefined as any, + }; +}; + +export default createTransformer(); +export { createTransformer }; diff --git a/src/postprocess.ts b/src/postprocess.ts index b86e72d6cb..f91876d3ab 100644 --- a/src/postprocess.ts +++ b/src/postprocess.ts @@ -16,26 +16,24 @@ function importBabelDeps() { istanbulPlugin = require('babel-plugin-istanbul').default; jestPreset = require('babel-preset-jest'); } -import { CompilerOptions } from 'typescript/lib/typescript'; +import { CompilerOptions } from 'typescript'; import { BabelTransformOptions, - CodeSourceMapPair, - JestConfig, PostProcessHook, - TransformOptions, + JestCacheKeyOptions, TsJestConfig, -} from './jest-types'; -import { logOnce } from './logger'; +} from './types'; +import { logOnce } from './utils/logger'; // Function that takes the transpiled typescript and runs it through babel/whatever. export function postProcessCode( compilerOptions: CompilerOptions, - jestConfig: JestConfig, + jestConfig: jest.ProjectConfig, tsJestConfig: TsJestConfig, - transformOptions: TransformOptions, - transpileOutput: CodeSourceMapPair, + transformOptions: jest.TransformOptions, + transpileOutput: jest.TransformedSource, filePath: string, -): CodeSourceMapPair { +): jest.TransformedSource { const postHook = getPostProcessHook( compilerOptions, jestConfig, @@ -58,11 +56,11 @@ function createBabelTransformer( delete options.filename; return ( - codeSourcemapPair: CodeSourceMapPair, + codeSourcemapPair: jest.TransformedSource, filename: string, - config: JestConfig, - transformOptions: TransformOptions, - ): CodeSourceMapPair => { + config: jest.ProjectConfig, + transformOptions: JestCacheKeyOptions, + ): jest.TransformedSource => { const theseOptions = Object.assign( { filename, inputSourceMap: codeSourcemapPair.map }, options, @@ -81,17 +79,18 @@ function createBabelTransformer( ], ]); } - // Babel has incorrect typings, where the map is an object instead of a string. So we have to typecast it here - return (babel.transform( + + // we typecast here because babel returns a more complete object than the one expected by jest + return babel.transform( codeSourcemapPair.code, theseOptions, - ) as any) as CodeSourceMapPair; + ) as jest.TransformedSource; }; } export const getPostProcessHook = ( tsCompilerOptions: CompilerOptions, - jestConfig: JestConfig, + jestConfig: jest.ProjectConfig, tsJestConfig: TsJestConfig, ): PostProcessHook => { if (tsJestConfig.skipBabel) { diff --git a/src/preprocessor.ts b/src/preprocess.ts similarity index 65% rename from src/preprocessor.ts rename to src/preprocess.ts index a5a04e8ad5..748a2aca82 100644 --- a/src/preprocessor.ts +++ b/src/preprocess.ts @@ -1,22 +1,14 @@ -import * as crypto from 'crypto'; -import { - BabelTransformOptions, - CodeSourceMapPair, - JestConfig, - Path, - TransformOptions, -} from './jest-types'; -import { flushLogs, logOnce } from './logger'; +import { flushLogs, logOnce } from './utils/logger'; import { postProcessCode } from './postprocess'; import { getTSConfig, getTSJestConfig, runTsDiagnostics } from './utils'; import { transpileTypescript } from './transpiler'; -export function process( +export default function preprocess( src: string, - filePath: Path, - jestConfig: JestConfig, - transformOptions: TransformOptions = { instrument: false }, -): CodeSourceMapPair | string { + filePath: jest.Path, + jestConfig: jest.ProjectConfig, + transformOptions: jest.TransformOptions, +): jest.TransformedSource | string { // transformOptions.instrument is a proxy for collectCoverage // https://github.com/kulshekhar/ts-jest/issues/201#issuecomment-300572902 const compilerOptions = getTSConfig(jestConfig.globals, jestConfig.rootDir); @@ -28,7 +20,7 @@ export function process( const isHtmlFile = /\.html$/.test(filePath); // This is to support angular 2. See https://github.com/kulshekhar/ts-jest/pull/145 - if (isHtmlFile && jestConfig.globals.__TRANSFORM_HTML__) { + if (isHtmlFile && (jestConfig.globals as any).__TRANSFORM_HTML__) { src = 'module.exports=' + JSON.stringify(src) + ';'; } @@ -76,24 +68,3 @@ export function process( return { code: outputText.code, map: outputText.map }; } - -/** - * This is the function Jest uses to check if it has the file already in cache - */ -export function getCacheKey( - fileData: string, - filePath: Path, - jestConfigStr: string, - transformOptions: TransformOptions = { instrument: false }, -): string { - const jestConfig: JestConfig = JSON.parse(jestConfigStr); - - const tsConfig = getTSConfig(jestConfig.globals, jestConfig.rootDir); - - return crypto - .createHash('md5') - .update(JSON.stringify(tsConfig), 'utf8') - .update(JSON.stringify(transformOptions), 'utf8') - .update(fileData + filePath + jestConfigStr, 'utf8') - .digest('hex'); -} diff --git a/src/transpile-if-ts.ts b/src/transpile-if-ts.ts deleted file mode 100644 index 95a2640f0e..0000000000 --- a/src/transpile-if-ts.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as tsc from 'typescript'; -import { getTSConfig, mockGlobalTSConfigSchema } from './utils'; -import { ConfigGlobals } from './jest-types'; - -export function transpileIfTypescript( - path: string, - contents: string, - config?: ConfigGlobals, - rootDir: string = '', -): string { - if (path && (path.endsWith('.tsx') || path.endsWith('.ts'))) { - const transpiled = tsc.transpileModule(contents, { - compilerOptions: getTSConfig( - config || mockGlobalTSConfigSchema(global), - rootDir, - ), - fileName: path, - }); - - return transpiled.outputText; - } - return contents; -} diff --git a/src/transpiler.ts b/src/transpiler.ts index 06ce887b2b..8c6721d857 100644 --- a/src/transpiler.ts +++ b/src/transpiler.ts @@ -1,13 +1,12 @@ import * as ts from 'typescript'; -import { logOnce } from './logger'; -import { CodeSourceMapPair } from './jest-types'; +import { logOnce } from './utils/logger'; // Takes the typescript code and by whatever method configured, makes it into javascript code. export function transpileTypescript( filePath: string, fileSrc: string, compilerOptions: ts.CompilerOptions, -): CodeSourceMapPair { +): jest.TransformedSource { logOnce('Compiling via normal transpileModule call'); const transpileOutput = transpileViaTranspileModule( filePath, diff --git a/src/jest-types.ts b/src/types.ts similarity index 65% rename from src/jest-types.ts rename to src/types.ts index f3ff30693d..e6456852b1 100644 --- a/src/jest-types.ts +++ b/src/types.ts @@ -1,17 +1,22 @@ import { TransformOptions as BabelTransformOpts } from 'babel-core'; -export interface TransformOptions { +export interface JestCacheKeyOptions { + rootDir: string; instrument: boolean; } -export type Path = string; - -export type Glob = string; - -export interface ConfigGlobals { - [key: string]: any; +export interface TsJestContext { + cache: any; + options: any; } +export type JestCacheKeyArguments = [ + string, + string, + string, + JestCacheKeyOptions +]; + export interface HasteConfig { defaultPlatform?: string | null; hasteImplModulePath?: string; @@ -24,17 +29,11 @@ export interface BabelTransformOptions extends BabelTransformOpts { } export type PostProcessHook = ( - codeSourcemapPair: CodeSourceMapPair, + codeSourcemapPair: jest.TransformedSource, filePath: string, - config: JestConfig, - transformOptions: TransformOptions, -) => CodeSourceMapPair; - -export type JestConfig = jest.InitialOptions & { - globals?: jest.ConfigGlobals & { - __TRANSFORM_HTML__?: boolean; - }; -}; + config: jest.ProjectConfig, + transformOptions: jest.TransformOptions, +) => jest.TransformedSource; export interface TsJestConfig { babelConfig?: BabelTransformOpts; @@ -53,8 +52,3 @@ export interface JestConfigNormalize { hasDeprecationWarnings: boolean; options: jest.DefaultOptions; } - -export interface CodeSourceMapPair { - code: string; - map: string; -} diff --git a/src/utils/constants.ts b/src/utils/constants.ts new file mode 100644 index 0000000000..b8556ac8ac --- /dev/null +++ b/src/utils/constants.ts @@ -0,0 +1,12 @@ +import { readFileSync } from 'fs'; +import { resolve } from 'path'; + +export const BABELRC_FILENAME = '.babelrc'; +export const BABELRC_JS_FILENAME = '.babelrc.js'; +export const BABEL_CONFIG_KEY = 'babel'; +export const TSCONFIG_FILENAME = 'tsconfig.json'; +export const TSCONFIG_GLOBALS_KEY = 'ts-jest'; +export const PACKAGE_JSON = 'package.json'; +export const MY_PACKAGE_CONTENT = readFileSync( + resolve(__dirname, '..', '..', PACKAGE_JSON), +); diff --git a/src/utils/get-babel-rc.ts b/src/utils/get-babel-rc.ts new file mode 100644 index 0000000000..b4734513a9 --- /dev/null +++ b/src/utils/get-babel-rc.ts @@ -0,0 +1,50 @@ +import { readFileSync, existsSync } from 'fs'; +import { dirname, join, resolve } from 'path'; +import { + BABELRC_FILENAME, + BABELRC_JS_FILENAME, + PACKAGE_JSON, + BABEL_CONFIG_KEY, +} from './constants'; +import { TsJestContext } from '../types'; + +// ideally we'd get that from babel-jest if it was exported, +// this is a pure translation from js +export default function getBabelRC(filename, { cache }: TsJestContext) { + const paths = []; + let directory = filename; + // tslint:disable-next-line:no-conditional-assignment + while (directory !== (directory = dirname(directory))) { + if (cache[directory]) { + break; + } + + paths.push(directory); + const configFilePath = join(directory, BABELRC_FILENAME); + if (existsSync(configFilePath)) { + cache[directory] = readFileSync(configFilePath, 'utf8'); + break; + } + const configJsFilePath = join(directory, BABELRC_JS_FILENAME); + if (existsSync(configJsFilePath)) { + cache[directory] = JSON.stringify(require(configJsFilePath)); + break; + } + const resolvedJsonFilePath = join(directory, PACKAGE_JSON); + const packageJsonFilePath = + resolvedJsonFilePath === PACKAGE_JSON + ? resolve(directory, PACKAGE_JSON) + : resolvedJsonFilePath; + if (existsSync(packageJsonFilePath)) { + const packageJsonFileContents = require(packageJsonFilePath); + if (packageJsonFileContents[BABEL_CONFIG_KEY]) { + cache[directory] = JSON.stringify( + packageJsonFileContents[BABEL_CONFIG_KEY], + ); + break; + } + } + } + paths.forEach(directoryPath => (cache[directoryPath] = cache[directory])); + return cache[directory] || ''; +} diff --git a/src/utils/get-cache-key.ts b/src/utils/get-cache-key.ts new file mode 100644 index 0000000000..d471bfe28d --- /dev/null +++ b/src/utils/get-cache-key.ts @@ -0,0 +1,31 @@ +import { createHash } from 'crypto'; +import { JestCacheKeyArguments, TsJestContext } from '../types'; +import { relative, resolve } from 'path'; +import { MY_PACKAGE_CONTENT } from './constants'; +import getBabelRC from './get-babel-rc'; +import { getTSConfig } from '.'; + +export default function getCacheKey( + args: JestCacheKeyArguments, + ctx: TsJestContext, +): string { + const [fileData, filePath, jestConfigString, { instrument, rootDir }] = args; + const glob = JSON.parse(jestConfigString).globals || {}; + return createHash('md5') + .update(MY_PACKAGE_CONTENT) + .update('\0', 'utf8') + .update(JSON.stringify(ctx.options)) + .update('\0', 'utf8') + .update(fileData) + .update('\0', 'utf8') + .update(relative(rootDir, filePath)) + .update('\0', 'utf8') + .update(jestConfigString) + .update('\0', 'utf8') + .update(JSON.stringify(getTSConfig(glob, rootDir))) + .update('\0', 'utf8') + .update(getBabelRC(filePath, ctx)) + .update('\0', 'utf8') + .update(instrument ? 'instrument' : '') + .digest('hex'); +} diff --git a/src/utils.ts b/src/utils/index.ts similarity index 94% rename from src/utils.ts rename to src/utils/index.ts index 8b9b03c198..a2c68b3365 100644 --- a/src/utils.ts +++ b/src/utils/index.ts @@ -3,12 +3,12 @@ import * as fs from 'fs'; import * as fsExtra from 'fs-extra'; import * as path from 'path'; import * as tsc from 'typescript'; -import { ConfigGlobals, JestConfig, TsJestConfig } from './jest-types'; +import { TsJestConfig } from '../types'; import { logOnce } from './logger'; import * as _ from 'lodash'; -export function getTSJestConfig(globals: ConfigGlobals): TsJestConfig { - return globals && globals['ts-jest'] ? globals['ts-jest'] : {}; +export function getTSJestConfig(globals: jest.ConfigGlobals): TsJestConfig { + return (globals && globals['ts-jest']) || {}; } function formatTsDiagnostics(errors: tsc.Diagnostic[]): string { @@ -88,7 +88,7 @@ function getPathToClosestTSConfig( } function getTSConfigPathFromConfig( - globals: ConfigGlobals, + globals: jest.ConfigGlobals, rootDir?: string, ): string { const defaultTSConfigFile = getPathToClosestTSConfig(rootDir); @@ -106,8 +106,8 @@ function getTSConfigPathFromConfig( } export function mockGlobalTSConfigSchema( - globals: ConfigGlobals, -): ConfigGlobals { + globals: jest.ConfigGlobals, +): jest.ConfigGlobals { const configPath = getTSConfigPathFromConfig(globals); return { 'ts-jest': { tsConfigFile: configPath } }; } @@ -161,7 +161,7 @@ function getTSConfig_local(globals, rootDir: string = '') { } export function cacheFile( - jestConfig: JestConfig, + jestConfig: jest.ProjectConfig, filePath: string, src: string, ): void { diff --git a/src/logger.ts b/src/utils/logger.ts similarity index 100% rename from src/logger.ts rename to src/utils/logger.ts diff --git a/tests/__tests__/get-cache-key.spec.ts b/tests/__tests__/get-cache-key.spec.ts index a85885b9e6..43e3e2e7a4 100644 --- a/tests/__tests__/get-cache-key.spec.ts +++ b/tests/__tests__/get-cache-key.spec.ts @@ -1,6 +1,9 @@ -import { getCacheKey } from '../../src/preprocessor'; -import { TransformOptions } from '../../src/jest-types'; +import getCacheKeyForArgs from '../../dist/utils/get-cache-key'; +import { TsJestContext } from '../../dist/types'; +const tsJestContext: TsJestContext = { cache: {}, options: {} }; +const getCacheKey = (...args: any[]) => + getCacheKeyForArgs(args as any, tsJestContext); describe('getCacheKey', () => { const src = 'console.log(123);'; const filepath = '/tmp/filepath'; @@ -18,7 +21,7 @@ describe('getCacheKey', () => { }, "testRegex": "(/__tests__/.*|(\\\\.|/)(test|spec))\\\\.(jsx?|tsx?)$" }`; - const options: TransformOptions = { instrument: false }; + const options: jest.TransformOptions = { instrument: false }; const originalHash = getCacheKey(src, filepath, configStr, options); it('should change hash when src changes', () => { @@ -40,7 +43,7 @@ describe('getCacheKey', () => { }); it('should change hash when transform options change', () => { - const newOptions: TransformOptions = { instrument: true }; + const newOptions: jest.TransformOptions = { instrument: true }; const newHash = getCacheKey(src, filepath, configStr, newOptions); expect(newHash).not.toBe(originalHash); }); diff --git a/tests/__tests__/transpiler.spec.ts b/tests/__tests__/transpiler.spec.ts index abaab22f45..4e10add7dc 100644 --- a/tests/__tests__/transpiler.spec.ts +++ b/tests/__tests__/transpiler.spec.ts @@ -2,22 +2,33 @@ import { transpileTypescript } from '../../src/transpiler'; import * as ts from 'typescript'; describe('transpileTypescript', () => { - - const compilerOptions: ts.CompilerOptions = {newLine: ts.NewLineKind.LineFeed}; + const compilerOptions: ts.CompilerOptions = { + newLine: ts.NewLineKind.LineFeed, + }; it('should transpile valid TS syntax', () => { - const result = transpileTypescript('valid.ts', 'var a = true;', compilerOptions); + const result = transpileTypescript( + 'valid.ts', + 'var a = true;', + compilerOptions, + ); expect(result.code).toBe('var a = true;\n'); }); it('should transpile valid TS syntax with type errors', () => { - const result = transpileTypescript('valid.ts', 'var a: string = true;', compilerOptions); + const result = transpileTypescript( + 'valid.ts', + 'var a: string = true;', + compilerOptions, + ); expect(result.code).toBe('var a = true;\n'); }); it('should throw an error when transpiling invalid TS syntax', () => { expect(() => { transpileTypescript('invalid.ts', 'var a = ;', compilerOptions); - }).toThrow('TypeScript compiler encountered syntax errors while transpiling. Errors: Expression expected.'); + }).toThrow( + 'TypeScript compiler encountered syntax errors while transpiling. Errors: Expression expected.', + ); }); }); diff --git a/tests/coverage-simple/.gitignore b/tests/coverage-simple/.gitignore new file mode 100644 index 0000000000..9e233d795a --- /dev/null +++ b/tests/coverage-simple/.gitignore @@ -0,0 +1 @@ +coverage-custom diff --git a/tests/coverage-simple/Hello.ts b/tests/coverage-simple/Hello.ts new file mode 100644 index 0000000000..3eaae5c40d --- /dev/null +++ b/tests/coverage-simple/Hello.ts @@ -0,0 +1,28 @@ +interface FooInterface { + foo: string; + bar: number; //This interface should be stripped and the line numbers should still fit. +} + +export class Hello { + constructor() { + const greeting = ` + this + is + a + multiline + greeting + `; + + this.unexcuted(() => {}); + + throw new Error('Hello error!'); + } + + unexcuted(action: () => void = () => {}): void { + if (action) { + action(); + } else { + console.log('unexcuted'); + } + } +} diff --git a/tests/coverage-simple/NullCoverage.js b/tests/coverage-simple/NullCoverage.js new file mode 100644 index 0000000000..c59dbbdef3 --- /dev/null +++ b/tests/coverage-simple/NullCoverage.js @@ -0,0 +1,6 @@ +function nullCoverageFunction(value) { + if (value) { + return value; + } + return null; +} diff --git a/tests/coverage-simple/__tests__/Hello.test.ts b/tests/coverage-simple/__tests__/Hello.test.ts new file mode 100644 index 0000000000..3df75018f9 --- /dev/null +++ b/tests/coverage-simple/__tests__/Hello.test.ts @@ -0,0 +1,9 @@ +declare var jest, describe, it, expect; + +import { Hello } from '../Hello'; + +describe('Hello Class', () => { + it('should throw an error on line 18', () => { + expect(() => new Hello()).toThrow(); + }); +}); diff --git a/tests/coverage-simple/package.json b/tests/coverage-simple/package.json new file mode 100644 index 0000000000..c577a32b44 --- /dev/null +++ b/tests/coverage-simple/package.json @@ -0,0 +1,22 @@ +{ + "jest": { + "transform": { + "^.+\\.tsx?$": "ts-jest" + }, + "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$", + "coverageReporters": [ + "lcov" + ], + "collectCoverageFrom": [ + "Hello.ts", + "NullCoverage.js" + ], + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "jsx", + "json" + ] + } +} diff --git a/tests/coverage-simple/tsconfig.json b/tests/coverage-simple/tsconfig.json new file mode 100644 index 0000000000..55f8667f97 --- /dev/null +++ b/tests/coverage-simple/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ES5", + "module": "commonjs", + "moduleResolution": "node", + "noEmitOnError": false, + "jsx": "react", + "allowJs": true + } +} diff --git a/tests/coverage-simple/yarn.lock b/tests/coverage-simple/yarn.lock new file mode 100644 index 0000000000..fb57ccd13a --- /dev/null +++ b/tests/coverage-simple/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000000..4eecabd0b4 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "sourceMap": false, + "removeComments": true, + "outDir": "dist", + "rootDir": "src", + }, + "include": ["src/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/tsconfig.json b/tsconfig.json index d5b6e37db0..d1a8c133ba 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "sourceMap": false, + "inlineSourceMap": true, "declaration": true, "target": "es5", "module": "commonjs", @@ -11,17 +12,13 @@ "noImplicitReturns": true, "removeComments": true, "strictNullChecks": false, - "inlineSourceMap": true, "jsx": "react", "emitDecoratorMetadata": true, "experimentalDecorators": true, "allowSyntheticDefaultImports": false, - "outDir": "dist", - "rootDir": "src", "skipLibCheck": true, "lib": ["es2015"], "types": ["jest"] }, - "include": ["src/**/*.ts", "src/**/*.tsx"], - "exclude": ["node_modules"] + "exclude": ["**/node_modules/**/*"] }