diff --git a/src/ts-jest-transformer.spec.ts b/src/ts-jest-transformer.spec.ts index de3741598c..519e687ed4 100644 --- a/src/ts-jest-transformer.spec.ts +++ b/src/ts-jest-transformer.spec.ts @@ -10,6 +10,7 @@ import { SOURCE_MAPPING_PREFIX, TsJestCompiler } from './compiler' import { CACHE_KEY_EL_SEPARATOR, TsJestTransformer } from './ts-jest-transformer' import type { DepGraphInfo } from './types' import { stringify } from './utils' +import { importer } from './utils/importer' import { sha1 } from './utils/sha1' const logTarget = logTargetMock() @@ -443,6 +444,18 @@ describe('TsJestTransformer', () => { expect(logTarget.filteredLines(LogLevels.warn)[0]).toMatchSnapshot() } }) + + test('should use afterHook file', () => { + importer.tryTheseOr = jest.fn().mockReturnValueOnce({ afterProcess: () => 'foo' }) + process.env.TS_JEST_HOOKS = __filename + + const fileContent = 'type Foo = number' + const filePath = 'foo.d.ts' + + expect(tr.process(fileContent, filePath, baseTransformOptions)).toEqual('foo') + + delete process.env.TS_JEST_HOOKS + }) }) describe('processAsync', () => { diff --git a/src/ts-jest-transformer.ts b/src/ts-jest-transformer.ts index 94b81922e0..24d951eb55 100644 --- a/src/ts-jest-transformer.ts +++ b/src/ts-jest-transformer.ts @@ -10,6 +10,7 @@ import { ConfigSet } from './config' import { DECLARATION_TYPE_EXT, JS_JSX_REGEX, TS_TSX_REGEX } from './constants' import type { CompilerInstance, DepGraphInfo, ProjectConfigTsJest, TransformOptionsTsJest } from './types' import { parse, stringify, JsonableValue, rootLogger } from './utils' +import { importer } from './utils/importer' import { Errors, interpolate } from './utils/messages' import { sha1 } from './utils/sha1' import { VersionCheckers } from './utils/version-checkers' @@ -24,6 +25,11 @@ interface CachedConfigSet { watchMode: boolean } +interface TsJestHooksMap { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + afterProcess?(args: any[], result: string | TransformedSource): string | TransformedSource | void +} + /** * @internal */ @@ -144,6 +150,13 @@ export class TsJestTransformer implements SyncTransformer { const isDefinitionFile = filePath.endsWith(DECLARATION_TYPE_EXT) const isJsFile = JS_JSX_REGEX.test(filePath) const isTsFile = !isDefinitionFile && TS_TSX_REGEX.test(filePath) + let hooksFile = process.env.TS_JEST_HOOKS + let hooks: TsJestHooksMap | undefined + /* istanbul ignore next (cover by e2e) */ + if (hooksFile) { + hooksFile = path.resolve(configs.cwd, hooksFile) + hooks = importer.tryTheseOr(hooksFile, {}) + } if (shouldStringifyContent) { // handles here what we should simply stringify result = `module.exports=${stringify(fileContent)}` @@ -179,6 +192,15 @@ export class TsJestTransformer implements SyncTransformer { // do not instrument here, jest will do it anyway afterwards result = babelJest.process(result, filePath, { ...transformOptions, instrument: false }) } + // This is not supposed to be a public API but we keep it as some people use it + if (hooks?.afterProcess) { + this._logger.debug({ fileName: filePath, hookName: 'afterProcess' }, 'calling afterProcess hook') + + const newResult = hooks.afterProcess([fileContent, filePath, transformOptions.config, transformOptions], result) + if (newResult) { + return newResult + } + } return result }