Skip to content

Commit be20a7c

Browse files
authored
feat(config): support after and afterDeclarations AST transformers (#1831)
1 parent 4eb56aa commit be20a7c

15 files changed

Lines changed: 445 additions & 61 deletions

File tree

docs/user/config/astTransformers.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ title: AST transformers option
55
`ts-jest` by default does hoisting for a few `jest` methods via a TypeScript AST transformer. One can also create custom
66
TypeScript AST transformers and provide them to `ts-jest` to include into compilation process.
77

8-
The option is `astTransformers` and it allows ones to specify which TypeScript AST transformers to use with `ts-jest`.
8+
The option is `astTransformers` and it allows ones to specify which 3 types of TypeScript AST transformers to use with `ts-jest`:
9+
10+
- `before` means your transformers get run before TS ones, which means your transformers will get raw TS syntax
11+
instead of transpiled syntax (e.g `import` instead of `require` or `define` ).
12+
- `after` means your transformers get run after TS ones, which gets transpiled syntax.
13+
- `afterDeclarations` means your transformers get run during `d.ts` generation phase, allowing you to transform output type declarations.
914

1015
### Examples
1116

@@ -17,7 +22,9 @@ module.exports = {
1722
// [...]
1823
globals: {
1924
'ts-jest': {
20-
astTransformers: ['my-custom-transformer'],
25+
astTransformers: {
26+
before: ['my-custom-transformer'],
27+
},
2128
}
2229
}
2330
};
@@ -32,7 +39,9 @@ module.exports = {
3239
"jest": {
3340
"globals": {
3441
"ts-jest": {
35-
astTransformers: ['my-custom-transformer'],
42+
astTransformers: {
43+
"before": ["my-custom-transformer"]
44+
}
3645
}
3746
}
3847
}
@@ -43,5 +52,4 @@ module.exports = {
4352

4453
### Writing custom TypeScript AST transformers
4554

46-
To write a custom TypeScript AST transformers, one can take a look at the one that `ts-jest` is using at
47-
https://github.com/kulshekhar/ts-jest/tree/master/src/transformers
55+
To write a custom TypeScript AST transformers, one can take a look at [the one](https://github.com/kulshekhar/ts-jest/tree/master/src/transformers) that `ts-jest` is using.

e2e/__tests__/__snapshots__/logger.test.ts.snap

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,117 @@ Array [
124124
]
125125
`;
126126
127+
exports[`ts-jest logging deprecation warning with astTransformers config as an object should pass using template "default" 1`] = `
128+
√ jest
129+
↳ exit code: 0
130+
===[ STDOUT ]===================================================================
131+
132+
===[ STDERR ]===================================================================
133+
PASS ./Hello.spec.ts
134+
Hello Class
135+
√ should create a new Hello
136+
137+
Test Suites: 1 passed, 1 total
138+
Tests: 1 passed, 1 total
139+
Snapshots: 0 total
140+
Time: XXs
141+
Ran all test suites.
142+
================================================================================
143+
`;
144+
145+
exports[`ts-jest logging deprecation warning with astTransformers config as an object should pass using template "with-babel-7" 1`] = `
146+
√ jest
147+
↳ exit code: 0
148+
===[ STDOUT ]===================================================================
149+
150+
===[ STDERR ]===================================================================
151+
PASS ./Hello.spec.ts
152+
Hello Class
153+
√ should create a new Hello
154+
155+
Test Suites: 1 passed, 1 total
156+
Tests: 1 passed, 1 total
157+
Snapshots: 0 total
158+
Time: XXs
159+
Ran all test suites.
160+
================================================================================
161+
`;
162+
163+
exports[`ts-jest logging deprecation warning with astTransformers config as an object should pass using template "with-babel-7-string-config" 1`] = `
164+
√ jest
165+
↳ exit code: 0
166+
===[ STDOUT ]===================================================================
167+
168+
===[ STDERR ]===================================================================
169+
PASS ./Hello.spec.ts
170+
Hello Class
171+
√ should create a new Hello
172+
173+
Test Suites: 1 passed, 1 total
174+
Tests: 1 passed, 1 total
175+
Snapshots: 0 total
176+
Time: XXs
177+
Ran all test suites.
178+
================================================================================
179+
`;
180+
181+
exports[`ts-jest logging deprecation warning with astTransformers config as string array should pass using template "default" 1`] = `
182+
√ jest
183+
↳ exit code: 0
184+
===[ STDOUT ]===================================================================
185+
186+
===[ STDERR ]===================================================================
187+
ts-jest[config] (WARN) The configuration for astTransformers as string[] is deprecated and will be removed in ts-jest 27. Please define your custom AST transformers in a form of an object. More information you can check online documentation https://kulshekhar.github.io/ts-jest/user/config/astTransformers
188+
PASS ./Hello.spec.ts
189+
Hello Class
190+
√ should create a new Hello
191+
192+
Test Suites: 1 passed, 1 total
193+
Tests: 1 passed, 1 total
194+
Snapshots: 0 total
195+
Time: XXs
196+
Ran all test suites.
197+
================================================================================
198+
`;
199+
200+
exports[`ts-jest logging deprecation warning with astTransformers config as string array should pass using template "with-babel-7" 1`] = `
201+
√ jest
202+
↳ exit code: 0
203+
===[ STDOUT ]===================================================================
204+
205+
===[ STDERR ]===================================================================
206+
ts-jest[config] (WARN) The configuration for astTransformers as string[] is deprecated and will be removed in ts-jest 27. Please define your custom AST transformers in a form of an object. More information you can check online documentation https://kulshekhar.github.io/ts-jest/user/config/astTransformers
207+
PASS ./Hello.spec.ts
208+
Hello Class
209+
√ should create a new Hello
210+
211+
Test Suites: 1 passed, 1 total
212+
Tests: 1 passed, 1 total
213+
Snapshots: 0 total
214+
Time: XXs
215+
Ran all test suites.
216+
================================================================================
217+
`;
218+
219+
exports[`ts-jest logging deprecation warning with astTransformers config as string array should pass using template "with-babel-7-string-config" 1`] = `
220+
√ jest
221+
↳ exit code: 0
222+
===[ STDOUT ]===================================================================
223+
224+
===[ STDERR ]===================================================================
225+
ts-jest[config] (WARN) The configuration for astTransformers as string[] is deprecated and will be removed in ts-jest 27. Please define your custom AST transformers in a form of an object. More information you can check online documentation https://kulshekhar.github.io/ts-jest/user/config/astTransformers
226+
PASS ./Hello.spec.ts
227+
Hello Class
228+
√ should create a new Hello
229+
230+
Test Suites: 1 passed, 1 total
231+
Tests: 1 passed, 1 total
232+
Snapshots: 0 total
233+
Time: XXs
234+
Ran all test suites.
235+
================================================================================
236+
`;
237+
127238
exports[`ts-jest logging with unsupported version test with TS_JEST_DISABLE_VER_CHECKER is not set in process.env should pass using template "with-unsupported-version" 1`] = `
128239
√ jest
129240
↳ exit code: 0

e2e/__tests__/logger.test.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ describe('ts-jest logging', () => {
4747
const filteredEntries = result.logFileEntries
4848
// keep only debug and above
4949
.filter(m => (m.context[LogContexts.logLevel] || 0) >= LogLevels.debug)
50-
// simplify entires
50+
// simplify entries
5151
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
5252
.map(e => result.normalize(`[level:${e.context[LogContexts.logLevel]}] ${e.message}`))
5353
expect(filteredEntries).toMatchSnapshot()
@@ -90,4 +90,38 @@ describe('ts-jest logging', () => {
9090
})
9191
})
9292
}
93+
94+
describe('deprecation warning', () => {
95+
describe('with astTransformers config as string array', () => {
96+
const testCase = configureTestCase('simple', {
97+
tsJestConfig: {
98+
astTransformers: []
99+
}
100+
})
101+
102+
testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => {
103+
it(testLabel, () => {
104+
const result = runTest()
105+
expect(result.status).toBe(0)
106+
expect(result).toMatchSnapshot()
107+
})
108+
})
109+
})
110+
111+
describe('with astTransformers config as an object', () => {
112+
const testCase = configureTestCase('simple', {
113+
tsJestConfig: {
114+
astTransformers: {}
115+
}
116+
})
117+
118+
testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => {
119+
it(testLabel, () => {
120+
const result = runTest()
121+
expect(result.status).toBe(0)
122+
expect(result).toMatchSnapshot()
123+
})
124+
})
125+
})
126+
})
93127
})

src/__helpers__/fakers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function tsJestConfig(options?: Partial<TsJestConfig>): TsJestConfig {
1616
return {
1717
isolatedModules: false,
1818
compiler: 'typescript',
19-
transformers: [],
19+
transformers: options?.transformers ?? Object.create(null),
2020
babelConfig: undefined,
2121
tsConfig: undefined,
2222
packageJson: undefined,

src/__mocks__/dummy-transformer.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const { LogContexts, LogLevels } = require('bs-logger')
2+
3+
function factory(cs) {
4+
const logger = cs.logger.child({ namespace: 'dummy-transformer' })
5+
const ts = cs.compilerModule
6+
7+
function createVisitor(_ctx, _) {
8+
return (node) => node
9+
}
10+
11+
return (ctx) =>
12+
logger.wrap({ [LogContexts.logLevel]: LogLevels.debug, call: null }, 'visitSourceFileNode(): dummy', (sf) =>
13+
ts.visitNode(sf, createVisitor(ctx, sf))
14+
)
15+
}
16+
17+
exports.factory = factory

src/compiler/instance.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const SOURCE_MAPPING_PREFIX = 'sourceMappingURL='
1515
/**
1616
* Update the output remapping the source map.
1717
*/
18-
function updateOutput(outputText: string, normalizedFileName: string, sourceMap: string) {
18+
function updateOutput(outputText: string, normalizedFileName: string, sourceMap: string): string {
1919
const base64Map = Buffer.from(updateSourceMap(sourceMap, normalizedFileName), 'utf8').toString('base64')
2020
const sourceMapContent = `data:application/json;charset=utf-8;base64,${base64Map}`
2121

@@ -45,7 +45,7 @@ const compileAndUpdateOutput = (compileFn: CompileFn, logger: Logger) => (
4545
code: string,
4646
fileName: string,
4747
lineOffset?: number,
48-
) => {
48+
): string => {
4949
logger.debug({ fileName }, 'compileAndUpdateOutput(): get compile output')
5050

5151
const [value, sourceMap] = compileFn(code, fileName, lineOffset)

src/compiler/language-service.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,26 @@ import * as _ts from 'typescript'
77

88
import type { ConfigSet } from '../config/config-set'
99
import { LINE_FEED } from '../constants'
10-
import { CompilerInstance, MemoryCache, SourceOutput, TSFile } from '../types'
10+
import { CompilerInstance, SourceOutput } from '../types'
1111
import { Errors, interpolate } from '../util/messages'
1212

1313
import { parse, stringify } from '../util/json'
1414
import { sha1 } from '../util/sha1'
1515

16+
/** where key is filepath */
17+
type TSFiles = Map<string, TSFile>
18+
19+
interface TSFile {
20+
text?: string
21+
output?: string
22+
version: number
23+
}
24+
25+
interface MemoryCache {
26+
resolvedModules: Map<string, string[]>
27+
files: TSFiles
28+
}
29+
1630
function doTypeChecking(
1731
configs: ConfigSet,
1832
diagnosedFiles: string[],

src/config/__snapshots__/config-set.spec.ts.snap

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`cacheKey should be a string 1`] = `"{\\"digest\\":\\"a0d51ca854194df8191d0e65c0ca4730f510f332\\",\\"jest\\":{\\"__backported\\":true,\\"globals\\":{}},\\"projectDepVersions\\":{\\"dev\\":\\"1.2.5\\",\\"opt\\":\\"1.2.3\\",\\"peer\\":\\"1.2.4\\",\\"std\\":\\"1.2.6\\"},\\"transformers\\":[\\"hoisting-jest-mock@1\\"],\\"tsJest\\":{\\"compiler\\":\\"typescript\\",\\"diagnostics\\":{\\"ignoreCodes\\":[6059,18002,18003],\\"pretty\\":true,\\"throws\\":true},\\"isolatedModules\\":false,\\"packageJson\\":{\\"kind\\":\\"file\\"},\\"transformers\\":[],\\"tsConfig\\":{\\"kind\\":\\"file\\",\\"value\\":\\"\\"}},\\"tsconfig\\":{\\"options\\":{\\"configFilePath\\":\\"\\",\\"declaration\\":false,\\"inlineSourceMap\\":false,\\"inlineSources\\":true,\\"module\\":1,\\"noEmit\\":false,\\"removeComments\\":false,\\"sourceMap\\":true,\\"target\\":1,\\"types\\":[]},\\"raw\\":{\\"compileOnSave\\":false,\\"compilerOptions\\":{\\"composite\\":true,\\"declaration\\":true,\\"types\\":[]},\\"exclude\\":[\\"foo/**/*\\"],\\"include\\":[\\"bar/**/*\\"]}}}"`;
3+
exports[`cacheKey should be a string 1`] = `"{\\"digest\\":\\"a0d51ca854194df8191d0e65c0ca4730f510f332\\",\\"jest\\":{\\"__backported\\":true,\\"globals\\":{}},\\"projectDepVersions\\":{\\"dev\\":\\"1.2.5\\",\\"opt\\":\\"1.2.3\\",\\"peer\\":\\"1.2.4\\",\\"std\\":\\"1.2.6\\"},\\"transformers\\":[\\"hoisting-jest-mock@1\\"],\\"tsJest\\":{\\"compiler\\":\\"typescript\\",\\"diagnostics\\":{\\"ignoreCodes\\":[6059,18002,18003],\\"pretty\\":true,\\"throws\\":true},\\"isolatedModules\\":false,\\"packageJson\\":{\\"kind\\":\\"file\\"},\\"transformers\\":{},\\"tsConfig\\":{\\"kind\\":\\"file\\",\\"value\\":\\"\\"}},\\"tsconfig\\":{\\"options\\":{\\"configFilePath\\":\\"\\",\\"declaration\\":false,\\"inlineSourceMap\\":false,\\"inlineSources\\":true,\\"module\\":1,\\"noEmit\\":false,\\"removeComments\\":false,\\"sourceMap\\":true,\\"target\\":1,\\"types\\":[]},\\"raw\\":{\\"compileOnSave\\":false,\\"compilerOptions\\":{\\"composite\\":true,\\"declaration\\":true,\\"types\\":[]},\\"exclude\\":[\\"foo/**/*\\"],\\"include\\":[\\"bar/**/*\\"]}}}"`;
44

55
exports[`isTestFile should return a boolean value whether the file matches test pattern 1`] = `true`;
66

@@ -67,7 +67,7 @@ Object {
6767
"value": undefined,
6868
},
6969
"stringifyContentPathRegex": undefined,
70-
"transformers": Array [],
70+
"transformers": Object {},
7171
"tsConfig": Object {
7272
"kind": "file",
7373
"value": "",
@@ -156,6 +156,45 @@ Array [
156156
]
157157
`;
158158

159+
exports[`tsCustomTransformers should return an object containing all resolved transformers 1`] = `
160+
Object {
161+
"before": Array [
162+
[Function],
163+
],
164+
}
165+
`;
166+
167+
exports[`tsCustomTransformers should return an object containing all resolved transformers 2`] = `
168+
Object {
169+
"before": Array [
170+
[Function],
171+
[Function],
172+
],
173+
}
174+
`;
175+
176+
exports[`tsCustomTransformers should return an object containing all resolved transformers 3`] = `
177+
Object {
178+
"after": Array [
179+
[Function],
180+
],
181+
"before": Array [
182+
[Function],
183+
],
184+
}
185+
`;
186+
187+
exports[`tsCustomTransformers should return an object containing all resolved transformers 4`] = `
188+
Object {
189+
"afterDeclarations": Array [
190+
[Function],
191+
],
192+
"before": Array [
193+
[Function],
194+
],
195+
}
196+
`;
197+
159198
exports[`tsJest should return correct defaults 1`] = `
160199
Object {
161200
"babelConfig": undefined,
@@ -175,10 +214,15 @@ Object {
175214
"value": undefined,
176215
},
177216
"stringifyContentPathRegex": undefined,
178-
"transformers": Array [],
217+
"transformers": Object {},
179218
"tsConfig": Object {
180219
"kind": "file",
181220
"value": undefined,
182221
},
183222
}
184223
`;
224+
225+
exports[`tsJest transformers should display deprecation warning message when config transformers is string array 1`] = `
226+
"[level:40] The configuration for astTransformers as string[] is deprecated and will be removed in ts-jest 27. Please define your custom AST transformers in a form of an object. More information you can check online documentation https://kulshekhar.github.io/ts-jest/user/config/astTransformers
227+
"
228+
`;

0 commit comments

Comments
 (0)