Skip to content

Commit

Permalink
feat(config): support after and afterDeclarations AST transformers (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ahnpnl authored Jul 28, 2020
1 parent 4eb56aa commit be20a7c
Show file tree
Hide file tree
Showing 15 changed files with 445 additions and 61 deletions.
18 changes: 13 additions & 5 deletions docs/user/config/astTransformers.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ title: AST transformers option
`ts-jest` by default does hoisting for a few `jest` methods via a TypeScript AST transformer. One can also create custom
TypeScript AST transformers and provide them to `ts-jest` to include into compilation process.

The option is `astTransformers` and it allows ones to specify which TypeScript AST transformers to use with `ts-jest`.
The option is `astTransformers` and it allows ones to specify which 3 types of TypeScript AST transformers to use with `ts-jest`:

- `before` means your transformers get run before TS ones, which means your transformers will get raw TS syntax
instead of transpiled syntax (e.g `import` instead of `require` or `define` ).
- `after` means your transformers get run after TS ones, which gets transpiled syntax.
- `afterDeclarations` means your transformers get run during `d.ts` generation phase, allowing you to transform output type declarations.

### Examples

Expand All @@ -17,7 +22,9 @@ module.exports = {
// [...]
globals: {
'ts-jest': {
astTransformers: ['my-custom-transformer'],
astTransformers: {
before: ['my-custom-transformer'],
},
}
}
};
Expand All @@ -32,7 +39,9 @@ module.exports = {
"jest": {
"globals": {
"ts-jest": {
astTransformers: ['my-custom-transformer'],
astTransformers: {
"before": ["my-custom-transformer"]
}
}
}
}
Expand All @@ -43,5 +52,4 @@ module.exports = {

### Writing custom TypeScript AST transformers

To write a custom TypeScript AST transformers, one can take a look at the one that `ts-jest` is using at
https://github.com/kulshekhar/ts-jest/tree/master/src/transformers
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.
111 changes: 111 additions & 0 deletions e2e/__tests__/__snapshots__/logger.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,117 @@ Array [
]
`;
exports[`ts-jest logging deprecation warning with astTransformers config as an object should pass using template "default" 1`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
===[ STDERR ]===================================================================
PASS ./Hello.spec.ts
Hello Class
√ should create a new Hello
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: XXs
Ran all test suites.
================================================================================
`;
exports[`ts-jest logging deprecation warning with astTransformers config as an object should pass using template "with-babel-7" 1`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
===[ STDERR ]===================================================================
PASS ./Hello.spec.ts
Hello Class
√ should create a new Hello
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: XXs
Ran all test suites.
================================================================================
`;
exports[`ts-jest logging deprecation warning with astTransformers config as an object should pass using template "with-babel-7-string-config" 1`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
===[ STDERR ]===================================================================
PASS ./Hello.spec.ts
Hello Class
√ should create a new Hello
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: XXs
Ran all test suites.
================================================================================
`;
exports[`ts-jest logging deprecation warning with astTransformers config as string array should pass using template "default" 1`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
===[ STDERR ]===================================================================
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
PASS ./Hello.spec.ts
Hello Class
√ should create a new Hello
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: XXs
Ran all test suites.
================================================================================
`;
exports[`ts-jest logging deprecation warning with astTransformers config as string array should pass using template "with-babel-7" 1`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
===[ STDERR ]===================================================================
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
PASS ./Hello.spec.ts
Hello Class
√ should create a new Hello
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: XXs
Ran all test suites.
================================================================================
`;
exports[`ts-jest logging deprecation warning with astTransformers config as string array should pass using template "with-babel-7-string-config" 1`] = `
√ jest
↳ exit code: 0
===[ STDOUT ]===================================================================
===[ STDERR ]===================================================================
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
PASS ./Hello.spec.ts
Hello Class
√ should create a new Hello
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: XXs
Ran all test suites.
================================================================================
`;
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`] = `
√ jest
↳ exit code: 0
Expand Down
36 changes: 35 additions & 1 deletion e2e/__tests__/logger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ describe('ts-jest logging', () => {
const filteredEntries = result.logFileEntries
// keep only debug and above
.filter(m => (m.context[LogContexts.logLevel] || 0) >= LogLevels.debug)
// simplify entires
// simplify entries
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
.map(e => result.normalize(`[level:${e.context[LogContexts.logLevel]}] ${e.message}`))
expect(filteredEntries).toMatchSnapshot()
Expand Down Expand Up @@ -90,4 +90,38 @@ describe('ts-jest logging', () => {
})
})
}

describe('deprecation warning', () => {
describe('with astTransformers config as string array', () => {
const testCase = configureTestCase('simple', {
tsJestConfig: {
astTransformers: []
}
})

testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => {
it(testLabel, () => {
const result = runTest()
expect(result.status).toBe(0)
expect(result).toMatchSnapshot()
})
})
})

describe('with astTransformers config as an object', () => {
const testCase = configureTestCase('simple', {
tsJestConfig: {
astTransformers: {}
}
})

testCase.runWithTemplates(allValidPackageSets, 0, (runTest, { testLabel }) => {
it(testLabel, () => {
const result = runTest()
expect(result.status).toBe(0)
expect(result).toMatchSnapshot()
})
})
})
})
})
2 changes: 1 addition & 1 deletion src/__helpers__/fakers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export function tsJestConfig(options?: Partial<TsJestConfig>): TsJestConfig {
return {
isolatedModules: false,
compiler: 'typescript',
transformers: [],
transformers: options?.transformers ?? Object.create(null),
babelConfig: undefined,
tsConfig: undefined,
packageJson: undefined,
Expand Down
17 changes: 17 additions & 0 deletions src/__mocks__/dummy-transformer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const { LogContexts, LogLevels } = require('bs-logger')

function factory(cs) {
const logger = cs.logger.child({ namespace: 'dummy-transformer' })
const ts = cs.compilerModule

function createVisitor(_ctx, _) {
return (node) => node
}

return (ctx) =>
logger.wrap({ [LogContexts.logLevel]: LogLevels.debug, call: null }, 'visitSourceFileNode(): dummy', (sf) =>
ts.visitNode(sf, createVisitor(ctx, sf))
)
}

exports.factory = factory
4 changes: 2 additions & 2 deletions src/compiler/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const SOURCE_MAPPING_PREFIX = 'sourceMappingURL='
/**
* Update the output remapping the source map.
*/
function updateOutput(outputText: string, normalizedFileName: string, sourceMap: string) {
function updateOutput(outputText: string, normalizedFileName: string, sourceMap: string): string {
const base64Map = Buffer.from(updateSourceMap(sourceMap, normalizedFileName), 'utf8').toString('base64')
const sourceMapContent = `data:application/json;charset=utf-8;base64,${base64Map}`

Expand Down Expand Up @@ -45,7 +45,7 @@ const compileAndUpdateOutput = (compileFn: CompileFn, logger: Logger) => (
code: string,
fileName: string,
lineOffset?: number,
) => {
): string => {
logger.debug({ fileName }, 'compileAndUpdateOutput(): get compile output')

const [value, sourceMap] = compileFn(code, fileName, lineOffset)
Expand Down
16 changes: 15 additions & 1 deletion src/compiler/language-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,26 @@ import * as _ts from 'typescript'

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

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

/** where key is filepath */
type TSFiles = Map<string, TSFile>

interface TSFile {
text?: string
output?: string
version: number
}

interface MemoryCache {
resolvedModules: Map<string, string[]>
files: TSFiles
}

function doTypeChecking(
configs: ConfigSet,
diagnosedFiles: string[],
Expand Down
50 changes: 47 additions & 3 deletions src/config/__snapshots__/config-set.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

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/**/*\\"]}}}"`;
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/**/*\\"]}}}"`;

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

Expand Down Expand Up @@ -67,7 +67,7 @@ Object {
"value": undefined,
},
"stringifyContentPathRegex": undefined,
"transformers": Array [],
"transformers": Object {},
"tsConfig": Object {
"kind": "file",
"value": "",
Expand Down Expand Up @@ -156,6 +156,45 @@ Array [
]
`;

exports[`tsCustomTransformers should return an object containing all resolved transformers 1`] = `
Object {
"before": Array [
[Function],
],
}
`;

exports[`tsCustomTransformers should return an object containing all resolved transformers 2`] = `
Object {
"before": Array [
[Function],
[Function],
],
}
`;

exports[`tsCustomTransformers should return an object containing all resolved transformers 3`] = `
Object {
"after": Array [
[Function],
],
"before": Array [
[Function],
],
}
`;

exports[`tsCustomTransformers should return an object containing all resolved transformers 4`] = `
Object {
"afterDeclarations": Array [
[Function],
],
"before": Array [
[Function],
],
}
`;

exports[`tsJest should return correct defaults 1`] = `
Object {
"babelConfig": undefined,
Expand All @@ -175,10 +214,15 @@ Object {
"value": undefined,
},
"stringifyContentPathRegex": undefined,
"transformers": Array [],
"transformers": Object {},
"tsConfig": Object {
"kind": "file",
"value": undefined,
},
}
`;

exports[`tsJest transformers should display deprecation warning message when config transformers is string array 1`] = `
"[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
"
`;
Loading

0 comments on commit be20a7c

Please sign in to comment.