Skip to content

Commit 3325186

Browse files
authored
feat(transformers): add path-mapping custom AST transformer (#1927)
Usage detail see https://kulshekhar.github.io/ts-jest/user/config/astTransformers
1 parent cd60dc7 commit 3325186

33 files changed

+4602
-29
lines changed

.eslintrc.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ module.exports = {
4141
'getter-return': 'warn',
4242
'guard-for-in': 'error',
4343
'id-match': 'error',
44+
'jest/valid-title': 'off',
45+
'jest/no-conditional-expect': 'off',
4446
'jsdoc/check-alignment': 'error',
4547
'jsdoc/check-indentation': 'error',
4648
'jsdoc/newline-after-description': 'warn',

docs/user/config/astTransformers.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,54 @@ module.exports = {
5050

5151
</div></div>
5252

53+
### Public transformers
54+
55+
`ts-jest` is able to expose transformers for public usage to provide the possibility to opt-in/out for users. Currently
56+
the exposed transformers are:
57+
58+
- `path-mapping` convert alias import/export to relative import/export path base on `paths` in `tsconfig`.
59+
This transformer works similar to `moduleNameMapper` in `jest.config.js`. When using this transformer, one might not need
60+
`moduleNameMapper` anymore.
61+
62+
#### Example of opt-in transformers
63+
64+
<div class="row"><div class="col-md-6" markdown="block">
65+
66+
```js
67+
// jest.config.js
68+
module.exports = {
69+
// [...]
70+
globals: {
71+
'ts-jest': {
72+
astTransformers: {
73+
before: ['ts-jest/dist/transformers/path-mapping'],
74+
},
75+
}
76+
}
77+
};
78+
```
79+
80+
</div><div class="col-md-6" markdown="block">
81+
82+
```js
83+
// OR package.json
84+
{
85+
// [...]
86+
"jest": {
87+
"globals": {
88+
"ts-jest": {
89+
astTransformers: {
90+
"before": ["ts-jest/dist/transformers/path-mapping"]
91+
}
92+
}
93+
}
94+
}
95+
}
96+
```
97+
98+
</div></div>
99+
100+
53101
### Writing custom TypeScript AST transformers
54102

55103
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.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { getWelcomeMessage } from '@share/foo'
2+
3+
test('should return welcome message', () => {
4+
const userName = 'github-user'
5+
6+
expect(getWelcomeMessage(userName)).toEqual(`yolo ${userName}`)
7+
})
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
test('should return welcome message', async () => {
2+
const userName = 'github-user'
3+
const foo = await import('@share/foo')
4+
5+
expect(foo.getWelcomeMessage(userName)).toEqual(`yolo ${userName}`)
6+
})
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { getWelcomeMessage } from '@share/export'
2+
3+
test('should return welcome message', async () => {
4+
const userName = ''
5+
6+
expect(getWelcomeMessage(userName)).toEqual(`yolo ${userName}`)
7+
})
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import foo from '@share/foo'
2+
3+
test('should return welcome message', () => {
4+
const userName = 'github-user'
5+
6+
expect(foo(userName)).toBe(`yolo ${userName}`)
7+
})
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import foo = require('@share/foo')
2+
3+
test('should return welcome message', () => {
4+
const userName = 'github-user'
5+
6+
expect(foo.getWelcomeMessage(userName)).toEqual(`yolo ${userName}`)
7+
})
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const foo = require('@share/foo')
2+
3+
test('should return welcome message', () => {
4+
const userName = 'github-user'
5+
6+
expect(foo.getWelcomeMessage(userName)).toEqual(`yolo ${userName}`)
7+
})
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import * as foo from '@share/foo'
2+
3+
test('should return welcome message', () => {
4+
const userName = 'github-user'
5+
6+
expect(foo.getWelcomeMessage(userName)).toEqual(`yolo ${userName}`)
7+
})
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { Foo } from '@share/foo'
2+
3+
test('should work', () => {
4+
const a: Foo = {
5+
bar: 1,
6+
}
7+
8+
expect(a).toBeTruthy()
9+
})
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { getWelcomeMessage } from '@share/foo'
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export function getWelcomeMessage(username: string): string {
2+
return `yolo ${username}`;
3+
}
4+
5+
function getMessage(username: string) {
6+
return getWelcomeMessage(username)
7+
}
8+
9+
export interface Foo {
10+
bar: number
11+
}
12+
13+
export default getMessage
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es5",
4+
"baseUrl": ".",
5+
"paths": {
6+
"@share/*": ["share/*"]
7+
}
8+
},
9+
"exclude": [
10+
"node_modules"
11+
]
12+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
module.exports = {
22
preset: 'ts-jest',
3-
testEnvironment: 'node',
3+
testEnvironment: 'node'
44
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.idea
2+
node_modules
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# A project to demonstrate how to setup `ts-jest` only to work together with `jest`
2+
3+
## Installation
4+
Run `yarn` to install dependencies
5+
6+
## Overview about configuration
7+
The project contains:
8+
- A `jest.config.js` which contains config for `ts-jest`.
9+
- A `tsconfig.json` which contains config for `typescript`.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { isStoreOwner } from './foo';
2+
import { getWelcomeMessage } from '@share/get-welcome-message';
3+
import type { Foo } from '@share/typings'
4+
5+
describe('Test optional chaining', () => {
6+
test(`should work`, () => {
7+
expect(isStoreOwner({
8+
isStoreOwner: false,
9+
})).toEqual(false)
10+
})
11+
12+
test(`test export *`, () => {
13+
expect(getWelcomeMessage('foo')).toEqual('yolo foo')
14+
})
15+
16+
test(`test import type`, () => {
17+
const foo: Foo = {
18+
bar: 1,
19+
}
20+
21+
expect(foo).toBeTruthy()
22+
})
23+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
interface User {
2+
isStoreOwner: boolean
3+
}
4+
5+
export const isStoreOwner = (user: User) => user?.isStoreOwner;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// For a detailed explanation regarding each configuration property, visit:
2+
// https://jestjs.io/docs/en/configuration.html
3+
/** @typedef {import('ts-jest')} */
4+
/** @type {import('@jest/types').Config.InitialOptions} */
5+
module.exports = {
6+
preset: 'ts-jest',
7+
globals: {
8+
'ts-jest': {
9+
astTransformers: {
10+
before: [
11+
'ts-jest/dist/transformers/path-mapping'
12+
]
13+
}
14+
}
15+
}
16+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "ts-jest-example",
3+
"version": "1.0.0",
4+
"license": "MIT",
5+
"devDependencies": {
6+
"@types/jest": "26.x",
7+
"jest": "26.x",
8+
"ts-jest": "26.x",
9+
"typescript": "~4.0.2"
10+
},
11+
"scripts": {
12+
"test": "jest"
13+
}
14+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { getWelcomeMessage } from './get-welcome-message';
2+
3+
describe(`getWelcomeMessage()`, (): void => {
4+
let username: string;
5+
6+
describe(`when the given username is a simple string`, (): void => {
7+
beforeEach(
8+
(): void => {
9+
username = `C0ZEN`;
10+
}
11+
);
12+
13+
it(`should return a message for this username`, (): void => {
14+
expect.assertions(1);
15+
16+
const result = getWelcomeMessage(username);
17+
18+
expect(result).toStrictEqual(`yolo C0ZEN`);
19+
});
20+
});
21+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function getWelcomeMessage(username: string): string {
2+
return `yolo ${username}`;
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface Foo {
2+
bar: number
3+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es5",
4+
"module": "commonjs",
5+
"baseUrl": ".",
6+
"declaration": true,
7+
"strict": true,
8+
"forceConsistentCasingInFileNames": true,
9+
"paths": {
10+
"@share/*": ["src/share/*"]
11+
}
12+
},
13+
"exclude": [
14+
"node_modules"
15+
]
16+
}

0 commit comments

Comments
 (0)