|
1 | | -import getCacheKey from './utils/get-cache-key'; |
2 | | -import preprocess from './preprocess'; |
3 | | - |
4 | | -const createTransformer = (options?: any): jest.Transformer => { |
5 | | - // options are always empty, must be the older jest API giving options here |
6 | | - return { |
7 | | - canInstrument: true, |
8 | | - getCacheKey, |
9 | | - process: preprocess, |
10 | | - createTransformer: undefined as any, |
11 | | - }; |
12 | | -}; |
13 | | - |
14 | | -const mod = createTransformer(); |
15 | | -mod.createTransformer = createTransformer; |
16 | | -export = mod; |
| 1 | +// tslint:disable:member-ordering |
| 2 | +import { TsJestInstance, TsJestGlobalOptions } from './types'; |
| 3 | +import TsProgram from './ts-program'; |
| 4 | + |
| 5 | +class TsJestTransformer implements jest.Transformer { |
| 6 | + private _instances = new Map<jest.Path, TsJestInstance>(); |
| 7 | + instanceFor( |
| 8 | + jestConfig: jest.ProjectConfig, |
| 9 | + rootDir: jest.Path = jestConfig.rootDir || process.cwd(), |
| 10 | + ): TsJestInstance { |
| 11 | + if (this._instances.has(rootDir)) { |
| 12 | + return this._instances.get(rootDir) as TsJestInstance; |
| 13 | + } |
| 14 | + const { globals = {} } = jestConfig as any; |
| 15 | + const options: TsJestGlobalOptions = { ...globals['ts-jest'] }; |
| 16 | + |
| 17 | + const shouldWrapHtml = !!globals.__TRANSFORM_HTML__; |
| 18 | + |
| 19 | + let tsProgram: TsProgram; |
| 20 | + const instance: TsJestInstance = { |
| 21 | + shouldWrapHtml, |
| 22 | + get tsProgram(): TsProgram { |
| 23 | + return tsProgram || (tsProgram = new TsProgram(rootDir, options)); |
| 24 | + }, |
| 25 | + get tsConfig() { |
| 26 | + return this.tsProgram.compilerOptions; |
| 27 | + }, |
| 28 | + // TODO: get using babel-jest |
| 29 | + useBabelJest: options.useBabelJest !== false, |
| 30 | + }; |
| 31 | + this._instances.set(rootDir, instance); |
| 32 | + return instance; |
| 33 | + } |
| 34 | + |
| 35 | + process( |
| 36 | + source: string, |
| 37 | + path: jest.Path, |
| 38 | + jestConfig: jest.ProjectConfig, |
| 39 | + transformOptions?: jest.TransformOptions, |
| 40 | + ): jest.TransformedSource | string { |
| 41 | + let result: string | jest.TransformedSource; |
| 42 | + |
| 43 | + // get the tranformer instance |
| 44 | + const instance = this.instanceFor(jestConfig); |
| 45 | + |
| 46 | + // transpile TS code (source maps are included) |
| 47 | + result = instance.tsProgram.transpileModule( |
| 48 | + path, |
| 49 | + source, |
| 50 | + transformOptions && transformOptions.instrument, |
| 51 | + ); |
| 52 | + |
| 53 | + // calling babel-jest transformer |
| 54 | + if (instance.useBabelJest) { |
| 55 | + result = this.babelJest.process( |
| 56 | + result, |
| 57 | + path, |
| 58 | + jestConfig, |
| 59 | + transformOptions, |
| 60 | + ); |
| 61 | + } |
| 62 | + |
| 63 | + return result; |
| 64 | + } |
| 65 | + |
| 66 | + private _babelJest!: jest.Transformer; |
| 67 | + get babelJest(): jest.Transformer { |
| 68 | + if (this._babelJest) return this._babelJest; // tslint:disable-line |
| 69 | + let babelJest = require('babel-jest'); |
| 70 | + if (typeof babelJest.createTransformer === 'function') { |
| 71 | + babelJest = babelJest.createTransformer(); |
| 72 | + } |
| 73 | + return (this._babelJest = babelJest); |
| 74 | + } |
| 75 | + |
| 76 | + // TODO: use jest-config package to try to get current config and see if we are going to use babel jest or not |
| 77 | + // in which case we'd return `true` there: |
| 78 | + // get canInstrument() {} |
| 79 | +} |
| 80 | + |
| 81 | +let transformer: jest.Transformer; |
| 82 | +function createTransformer() { |
| 83 | + return (transformer = new TsJestTransformer()); |
| 84 | +} |
| 85 | +function tsProcess(...args: any[]): any { |
| 86 | + return (createTransformer() as any).process(...args); |
| 87 | +} |
| 88 | + |
| 89 | +export { createTransformer, tsProcess as process }; |
0 commit comments