Skip to content

Commit 249aca1

Browse files
committed
feat(babel): alternative setup babel/TS (#311)
BREAKING CHANGE: add an alternative preset for babel and restructures the whole repository to treat babel and ts-jest equally. Furthermore `ts-jest` is not a dependency of the preset anymore. The jest config and package.json of users will have to be adjusted, see the CHANGELOG.md for migration information. Closes #308
1 parent f925564 commit 249aca1

32 files changed

+1987
-111
lines changed

.circleci/config.yml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,27 @@ jobs:
4747
at: .
4848
# skipping cache here as it created issues with the preset in the root
4949
# not being used, as older version in cache was available
50-
- run: 'sudo yarn global add greenkeeper-lockfile@2'
51-
- run: 'greenkeeper-lockfile-update'
50+
- run:
51+
name: Greenkeeper - update lockfile
52+
command: |
53+
sudo yarn global add greenkeeper-lockfile@2
54+
greenkeeper-lockfile-update
5255
- run:
5356
name: Install Example Dependencies
5457
command: |
5558
cd example
5659
yarn install --frozen-lockfile
5760
- run:
58-
name: Test Example
61+
name: Test Example - ts-jest preset
5962
command: |
6063
cd example
61-
yarn test:ci
64+
yarn test:ci:ts-jest
6265
yarn test:coverage
66+
- run:
67+
name: Test Example - babel preset
68+
command: |
69+
cd example
70+
yarn test:ci:babel
6371
6472
workflows:
6573
version: 2

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
## Changelog (master)
22

3+
#### Features
4+
* (**BREAKING**): Add preset `babel` as transpilation alternative to `ts-jest` and remove `ts-jest` as dependency ([#317](https://github.com/thymikee/jest-preset-angular/pull/317)).
5+
6+
#### Migration Guide
7+
* The preset reference in the jest config has to be updated from `"jest-preset-angular"` to `"jest-preset-angular/build/ts-jest"`. To use babel, replace `ts-jest` with `babel`. Furthermore, when using `ts-jest`, it has to be added as `devDependency` to the project, or `babel` packages alternatively (see README.md).
8+
39
### v8.0.0
410

511
#### Features

README.md

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ This is a part of the article: [Testing Angular faster with Jest](https://www.xf
99

1010
_Note: This preset does not suport AngularJS (1.x). If you want to set up Jest with AngularJS, please see [this blog post](https://medium.com/aya-experience/testing-an-angularjs-app-with-jest-3029a613251)._
1111

12+
This package actually contains two presets, one for `ts-jest`, which uses the official TypeScript compiler internally, and one for `babel`, which strips away the type annotations and simply transforms the JavaScript. If you are not sure, try to use `ts-jest`, to also type-check your test files.
13+
14+
1215
## Installation
1316

1417
```bash
@@ -19,6 +22,26 @@ npm install -D jest jest-preset-angular @types/jest
1922

2023
This will install `jest`, `@types/jest`, `ts-jest` as dependencies needed to run with Angular projects.
2124

25+
Additionally you need `ts-jest` or `babel` packages.
26+
27+
### ts-jest
28+
```bash
29+
yarn add -D ts-jest
30+
#or
31+
npm install -D ts-jest
32+
```
33+
34+
`ts-jest` uses the TypeScript compiler to generate JavaScript.
35+
36+
### babel
37+
```bash
38+
yarn add -D @babel/core @babel/preset-typescript @babel/preset-env @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators babel-plugin-transform-typescript-metadata babel-plugin-const-enum
39+
#or
40+
npm install -D @babel/core @babel/preset-typescript @babel/preset-env @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators babel-plugin-transform-typescript-metadata babel-plugin-const-enum
41+
```
42+
43+
`babel` uses the babel compiler to generate JavaScript, without type-checking your test files before doing so. You can still do type-checking using `tsc --noEmit`. For additional TypeScript-supported language features you might have to install even more babel packages. Note that `babel` also can differ slightly from `tsc`, e. g. in compiling a class to a function.
44+
2245
## Usage
2346

2447
In `src` directory create `setupJest.ts` file with following contents:
@@ -35,17 +58,42 @@ _Note: feel free to copy the [`jestGlobalMocks.ts`](https://github.com/thymikee/
3558
```json
3659
{
3760
"jest": {
38-
"preset": "jest-preset-angular",
61+
"preset": "jest-preset-angular/build/ts-jest",
3962
"setupFilesAfterEnv": ["<rootDir>/src/setupJest.ts"]
4063
}
4164
}
4265
```
4366

67+
or for `babel`:
68+
```json
69+
{
70+
"jest": {
71+
"preset": "jest-preset-angular/build/babel",
72+
"setupFilesAfterEnv": ["<rootDir>/src/setupJest.ts"]
73+
}
74+
}
75+
```
76+
77+
When using babel, also a `babel.config.js` on the project root level is required:
78+
```js
79+
const { babelAngularConfig } = require('jest-preset-angular/build/babel/babel.config')
80+
module.exports = api => {
81+
api.cache(false)
82+
return {
83+
presets: babelAngularConfig.presets,
84+
plugins: [
85+
...babelAngularConfig.plugins,
86+
// additional plugins
87+
]
88+
}
89+
}
90+
```
91+
4492
### Avoid karma conflicts
4593
By Angular CLI defaults you'll have a `src/test.ts` file which will be picked up by jest. To circumvent this you can either rename it to `src/karmaTest.ts` or hide it from jest by adding `<rootDir>/src/test.ts` to jest `testPathIgnorePatterns` option.
4694

4795

48-
## Exposed [configuration](https://github.com/thymikee/jest-preset-angular/blob/master/jest-preset.js)
96+
## Exposed [`ts-jest` configuration](https://github.com/thymikee/jest-preset-angular/blob/master/src/ts-jest/jest-preset.js)
4997

5098
```js
5199
module.exports = {
@@ -78,11 +126,13 @@ module.exports = {
78126
};
79127
```
80128

129+
Note that the [`babel` configuration](https://github.com/thymikee/jest-preset-angular/blob/master/src/babel/jest-preset.js) looks different.
130+
81131
### Brief explanation of config
82132

83133
- `<rootDir>` is a special syntax for root of your project (here by default it's project's root /)
84134
- we're using some `"globals"` to pass information about where our tsconfig.json file is that we'd like to be able to transform HTML files through ts-jest
85-
- `"transform"` – run every TS, JS, or HTML file through so called _preprocessor_ (we'll get there); this lets Jest understand non-JS syntax
135+
- `"transform"` – run every TS, JS, or HTML file through so called _preprocessor_, in our case just `ts-jest` or `babel-jest`; this lets Jest understand non-JS syntax
86136
- `"testMatch"` – we want to run Jest on files that matches this glob
87137
- `"moduleFileExtensions"` – our modules are TypeScript and JavaScript files
88138
- `"moduleNameMapper"` – if you're using absolute imports here's how to tell Jest where to look for them; uses regex

example/babel.config.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const { babelAngularConfig } = require('jest-preset-angular/build/babel/babel.config')
2+
module.exports = api => {
3+
api.cache(false)
4+
return {
5+
presets: babelAngularConfig.presets,
6+
plugins: [
7+
...babelAngularConfig.plugins,
8+
// your plugins
9+
]
10+
}
11+
}
12+

example/get-test-mode.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const defaultTestMode = 'ts-jest';
2+
const envTestModeKey = 'JPA_TEST_MODE';
3+
4+
module.exports = {
5+
getTestMode() {
6+
if (process.env && envTestModeKey in process.env && typeof process.env[envTestModeKey] === 'string') {
7+
return process.env[envTestModeKey];
8+
}
9+
return defaultTestMode;
10+
}
11+
}

example/jest.config.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
const { getTestMode } = require('./get-test-mode');
2+
13
module.exports = {
2-
preset: "jest-preset-angular",
4+
preset: `jest-preset-angular/build/${getTestMode()}`,
35
snapshotSerializers: [
46
"jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js",
57
"jest-preset-angular/build/AngularSnapshotSerializer.js",

example/package.json

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
"build": "ng build",
99
"test": "jest",
1010
"test:watch": "jest --watch",
11-
"test:ci": "jest --runInBand",
12-
"test:coverage": "jest --coverage"
11+
"test:ci": "yarn test:ci:ts-jest && yarn test:ci:babel",
12+
"test:ci:babel": "cross-env JPA_TEST_MODE=babel jest --runInBand",
13+
"test:ci:ts-jest": "cross-env JPA_TEST_MODE=ts-jest jest --runInBand",
14+
"test:coverage": "cross-env JPA_TEST_MODE=ts-jest jest --coverage"
1315
},
1416
"private": true,
1517
"dependencies": {
@@ -30,10 +32,21 @@
3032
"@angular/cli": "~8.3.4",
3133
"@angular/compiler-cli": "~8.2.5",
3234
"@angular/language-service": "~8.2.5",
35+
"@babel/core": "^7.6.4",
36+
"@babel/plugin-proposal-class-properties": "^7.5.5",
37+
"@babel/plugin-proposal-decorators": "^7.6.0",
38+
"@babel/preset-env": "^7.6.2",
39+
"@babel/preset-typescript": "^7.6.0",
3340
"@types/jest": "^24.0.0",
3441
"@types/node": "^11.0.0",
42+
"babel-jest": "^24.9.0",
43+
"babel-plugin-const-enum": "^0.0.2",
44+
"babel-plugin-transform-typescript-metadata": "^0.2.2",
45+
"cross-env": "^6.0.3",
3546
"jest": "^24.0.0",
3647
"jest-preset-angular": "file:../",
48+
"prettier": "^1.18.2",
49+
"ts-jest": "^24.1.0",
3750
"ts-node": "^8.0.3",
3851
"typescript": "~3.5.3"
3952
}

example/src/app/calc/__snapshots__/calc.component.spec.ts.snap

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
1+
import { async, ComponentFixture } from '@angular/core/testing';
22

33
import { configureTests, ConfigureFn } from '@lib/testing';
44

@@ -8,23 +8,50 @@ describe('CalcComponent', () => {
88
let component: CalcComponent;
99
let fixture: ComponentFixture<CalcComponent>;
1010

11-
beforeEach(
12-
async(() => {
13-
const configure: ConfigureFn = testBed => {
14-
testBed.configureTestingModule({
15-
declarations: [CalcComponent]
16-
});
17-
};
18-
19-
configureTests(configure).then(testBed => {
20-
fixture = testBed.createComponent(CalcComponent);
21-
component = fixture.componentInstance;
22-
fixture.detectChanges();
11+
beforeEach(async(() => {
12+
const configure: ConfigureFn = testBed => {
13+
testBed.configureTestingModule({
14+
declarations: [CalcComponent]
2315
});
24-
})
25-
);
16+
};
17+
18+
configureTests(configure).then(testBed => {
19+
fixture = testBed.createComponent(CalcComponent);
20+
component = fixture.componentInstance;
21+
fixture.detectChanges();
22+
});
23+
}));
2624

2725
it('should snap', () => {
28-
expect(fixture).toMatchSnapshot();
26+
if (global['JpaTestMode'] === 'ts-jest') {
27+
expect(fixture).toMatchInlineSnapshot(`
28+
<app-calc
29+
hasAClass="false"
30+
image={[Function String]}
31+
prop1={[Function Number]}
32+
>
33+
<p
34+
class="a-default-class"
35+
>
36+
calc works! 1337 another text node test-image-stub
37+
</p>
38+
</app-calc>
39+
`);
40+
} else {
41+
expect(fixture).toMatchInlineSnapshot(`
42+
<app-calc
43+
hasAClass="false"
44+
image={[Function String]}
45+
observable$="undefined"
46+
prop1={[Function Number]}
47+
>
48+
<p
49+
class="a-default-class"
50+
>
51+
calc works! 1337 another text node test-image-stub
52+
</p>
53+
</app-calc>
54+
`);
55+
}
2956
});
3057
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Injectable } from "@angular/core";
2+
import { HeroCategory, HeroColor } from "./hero-properties";
3+
4+
@Injectable({
5+
providedIn: "root"
6+
})
7+
export class HeroCategoryService {
8+
getCategoryForHero(heroName: string): HeroCategory {
9+
switch (heroName) {
10+
case "Joker":
11+
return HeroCategory.Evil;
12+
case "Batman":
13+
return HeroCategory.Good;
14+
default:
15+
return HeroCategory.Neutral;
16+
}
17+
}
18+
19+
getColorForHero(heroName: string): HeroColor {
20+
switch (heroName) {
21+
case "Joker":
22+
return HeroColor.Purple;
23+
case "Batman":
24+
return HeroColor.Black;
25+
case "Catwoman":
26+
return HeroColor.Black;
27+
default:
28+
return HeroColor.Transparent;
29+
}
30+
}
31+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { async } from "@angular/core/testing";
2+
3+
import { HeroCategoryService } from "./hero-category.service";
4+
import { HeroCategory, HeroColor } from './hero-properties';
5+
6+
describe("HeroCategoryService", () => {
7+
let service: HeroCategoryService;
8+
9+
beforeEach(() => (service = new HeroCategoryService()));
10+
11+
it("should create", () => {
12+
expect(service).toBeTruthy();
13+
});
14+
15+
it("should return the right category for heroes", () => {
16+
expect(service.getCategoryForHero("Batman")).toEqual(HeroCategory.Good);
17+
expect(service.getCategoryForHero("Joker")).toEqual(HeroCategory.Evil);
18+
expect(service.getCategoryForHero("Catwoman")).toEqual(HeroCategory.Neutral);
19+
});
20+
21+
it("should return the right color for heroes", () => {
22+
expect(service.getColorForHero("Batman")).toEqual(HeroColor.Black);
23+
expect(service.getColorForHero("Joker")).toEqual(HeroColor.Purple);
24+
expect(service.getColorForHero("The Penguin")).toEqual(HeroColor.Transparent);
25+
});
26+
27+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
export enum HeroCategory {
3+
Evil,
4+
Good,
5+
Neutral
6+
}
7+
8+
export const enum HeroColor {
9+
Black = "#000000",
10+
Purple = "#551A8B",
11+
Transparent = "#00000000"
12+
}

example/src/setupJest.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
import 'jest-preset-angular';
22
import './jestGlobalMocks';
3+
4+
// for example app testing only
5+
import { getTestMode } from '../get-test-mode';
6+
global['JpaTestMode'] = getTestMode()

0 commit comments

Comments
 (0)