jest-preset-angular 7.1.1 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/launch.json +36 -0
- package/CHANGELOG.md +22 -2
- package/README.md +30 -13
- package/build/AngularNoNgAttributesSnapshotSerializer.js +36 -0
- package/build/AngularSnapshotSerializer.js +49 -0
- package/{HTMLCommentSerializer.js → build/HTMLCommentSerializer.js} +11 -14
- package/{InlineHtmlStripStylesTransformer.js → build/InlineFilesTransformer.js} +31 -32
- package/build/StripStylesTransformer.js +122 -0
- package/build/TransformUtils.js +20 -0
- package/build/reflectMetadata.js +21 -0
- package/build/setupJest.js +12 -0
- package/build/zone-patch/index.js +95 -0
- package/index.js +1 -1
- package/jest-preset.js +9 -6
- package/package.json +5 -5
- package/tsconfig.json +2 -2
- package/yarn-error.log +3628 -0
- package/AngularNoNgAttributesSnapshotSerializer.js +0 -30
- package/AngularSnapshotSerializer.js +0 -67
- package/setupJest.js +0 -37
- package/zone-patch/LICENSE +0 -29
- package/zone-patch/README.md +0 -6
- package/zone-patch/index.js +0 -108
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Use IntelliSense to learn about possible attributes.
|
|
3
|
+
// Hover to view descriptions of existing attributes.
|
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
{
|
|
8
|
+
"type": "node",
|
|
9
|
+
"request": "attach",
|
|
10
|
+
"name": "Attach to 9226",
|
|
11
|
+
"port": 9226,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"type": "node",
|
|
15
|
+
"name": "vscode-jest-tests",
|
|
16
|
+
"request": "launch",
|
|
17
|
+
"args": [
|
|
18
|
+
"--runInBand"
|
|
19
|
+
],
|
|
20
|
+
"cwd": "${workspaceFolder}",
|
|
21
|
+
"console": "integratedTerminal",
|
|
22
|
+
"internalConsoleOptions": "neverOpen",
|
|
23
|
+
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"type": "node",
|
|
27
|
+
"request": "launch",
|
|
28
|
+
"name": "Launch Program",
|
|
29
|
+
"program": "${workspaceFolder}/index.js",
|
|
30
|
+
"preLaunchTask": "tsc: build - tsconfig.json",
|
|
31
|
+
"outFiles": [
|
|
32
|
+
"${workspaceFolder}/./**/*.js"
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
## Changelog (master)
|
|
2
2
|
|
|
3
|
+
### v8.0.0
|
|
4
|
+
|
|
5
|
+
#### Features
|
|
6
|
+
* (**BREAKING**): Refine ast-transformer behavior: only transform `styles`-assignments inside @Component ([#261](https://github.com/thymikee/jest-preset-angular/pull/261)) and TypeScript v2.9 `createStringLiteral` is polyfilled if an older version is used ([#272](https://github.com/thymikee/jest-preset-angular/issues/272)).
|
|
7
|
+
* (**BREAKING**): Restructure project with `src` and `build` folder ([#307](https://github.com/thymikee/jest-preset-angular/pull/307)).
|
|
8
|
+
* (**BREAKING**): Support `tsconfig.spec.json` in root folder by default ([#309](https://github.com/thymikee/jest-preset-angular/pull/309)).
|
|
9
|
+
* (**BREAKING**): Enable AngularNoAngularNoNgAttributesSnapshotSerializer (created in [#97](https://github.com/thymikee/jest-preset-angular/pull/97)) by default ([#318](https://github.com/thymikee/jest-preset-angular/pull/318)).
|
|
10
|
+
* Remove `core-js` dependency by using internal, minimal reflect-metadata ([#315](https://github.com/thymikee/jest-preset-angular/pull/315)).
|
|
11
|
+
|
|
12
|
+
#### Chore && Maintenance
|
|
13
|
+
* Update example app to match Angular 8 Boilerplate ([#311](https://github.com/thymikee/jest-preset-angular/pull/311)).
|
|
14
|
+
* Update example app to not use karma, extract jest config, fix paths ([#316](https://github.com/thymikee/jest-preset-angular/pull/316)).
|
|
15
|
+
* Update jsdom to current version 15 ([#318](https://github.com/thymikee/jest-preset-angular/pull/318)).
|
|
16
|
+
|
|
17
|
+
#### Migration Guide
|
|
18
|
+
* If the `astTransformers` are referenced in a custom `jest` config, `[ 'jest-preset-angular/build/InlineFilesTransformer', 'jest-preset-angular/build/StripStylesTransformer']` have to be set instead.
|
|
19
|
+
* Serializers, transformers and `setupJest` have to be referenced from the `jest-preset-angular/build/`-folder in a custom config. Existing references have to be aligned.
|
|
20
|
+
* If your `tsconfig.spec.json` is located in `src`, move it to your root folder and adjust the referenced files and paths inside, or align your jest configuration as discussed in the [README.md](https://github.com/thymikee/jest-preset-angular/blob/master/README.md#custom-tsconfig).
|
|
21
|
+
* In an Angular 8 project or higher, `core-js` should no longer be a dependency declared in `package.json`, unless it's imported manually in the code.
|
|
22
|
+
|
|
3
23
|
### v7.1.0
|
|
4
24
|
|
|
5
25
|
#### Features
|
|
@@ -27,7 +47,7 @@
|
|
|
27
47
|
#### Migration Guide
|
|
28
48
|
|
|
29
49
|
* If `global` and `transform` are not set in your configuration in `jest.config.json`, `jest.config.js` or `package.json`, you are done.
|
|
30
|
-
* If the `global` value of the configuration was
|
|
50
|
+
* If the `global` value of the configuration was overridden, adjust
|
|
31
51
|
* The option `"__TRANSFORM_HTML__": true` is not required anymore. Instead the `"stringifyContentPathRegex": "\\.html$"` should be used inside the `ts-jest`-configuration.
|
|
32
52
|
* Change the assignment identifier from `tsConfigFile` to `tsConfig`.
|
|
33
53
|
* Add the `astTransformers: [require.resolve('jest-preset-angular/InlineHtmlStripStylesTransformer')]` so Jest can work with `templateUrl`-assignments in Component decorators.
|
|
@@ -56,7 +76,7 @@
|
|
|
56
76
|
|
|
57
77
|
### v5.2.2
|
|
58
78
|
|
|
59
|
-
* Fix: specify angular modules as
|
|
79
|
+
* Fix: specify angular modules as peerDependencies ([#141](https://github.com/thymikee/jest-preset-angular/pull/141))
|
|
60
80
|
* Fix: update `STYLE_URLS_REGEX` to not break on multiple new lines ([#139](https://github.com/thymikee/jest-preset-angular/pull/139))
|
|
61
81
|
* Docs: add more troubleshooting docs ([#129](https://github.com/thymikee/jest-preset-angular/pull/129))
|
|
62
82
|
|
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ import 'jest-preset-angular';
|
|
|
28
28
|
import './jestGlobalMocks'; // browser mocks globally available for every test
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
_Note: feel free to copy the `jestGlobalMocks.ts` file from the example directory and save it next to the `setupJest.ts` file._
|
|
31
|
+
_Note: feel free to copy the [`jestGlobalMocks.ts`](https://github.com/thymikee/jest-preset-angular/blob/master/example/src/jestGlobalMocks.ts) file from the example directory and save it next to the `setupJest.ts` file._
|
|
32
32
|
|
|
33
33
|
...and include this in your `package.json`:
|
|
34
34
|
|
|
@@ -51,9 +51,12 @@ By Angular CLI defaults you'll have a `src/test.ts` file which will be picked up
|
|
|
51
51
|
module.exports = {
|
|
52
52
|
globals: {
|
|
53
53
|
'ts-jest': {
|
|
54
|
-
tsConfig: '<rootDir>/
|
|
54
|
+
tsConfig: '<rootDir>/tsconfig.spec.json',
|
|
55
55
|
stringifyContentPathRegex: '\\.html$',
|
|
56
|
-
astTransformers: [
|
|
56
|
+
astTransformers: [
|
|
57
|
+
'jest-preset-angular/build/InlineFilesTransformer',
|
|
58
|
+
'jest-preset-angular/build/StripStylesTransformer'
|
|
59
|
+
],
|
|
57
60
|
},
|
|
58
61
|
},
|
|
59
62
|
transform: {
|
|
@@ -69,8 +72,8 @@ module.exports = {
|
|
|
69
72
|
},
|
|
70
73
|
transformIgnorePatterns: ['node_modules/(?!@ngrx)'],
|
|
71
74
|
snapshotSerializers: [
|
|
72
|
-
'jest-preset-angular/AngularSnapshotSerializer.js',
|
|
73
|
-
'jest-preset-angular/HTMLCommentSerializer.js',
|
|
75
|
+
'jest-preset-angular/build/AngularSnapshotSerializer.js',
|
|
76
|
+
'jest-preset-angular/build/HTMLCommentSerializer.js',
|
|
74
77
|
],
|
|
75
78
|
};
|
|
76
79
|
```
|
|
@@ -229,6 +232,15 @@ describe('Component snapshots', () => {
|
|
|
229
232
|
|
|
230
233
|
Problems may arise if you're using custom builds (this preset is tailored for `angular-cli` as firstly priority). Please be advised that every entry in default configuration may be overridden to best suite your app's needs.
|
|
231
234
|
|
|
235
|
+
### Can't resolve all parameters for SomeClass(?)
|
|
236
|
+
|
|
237
|
+
This is related to Angular's reflection and also depends on a reflection library, as e. g. included in `core-js`. We use our own minimal reflection that satisfy Angular's current requirements, but in case these change, you can install `core-js` and import the reflection library in your `setupJest.ts`:
|
|
238
|
+
```typescript
|
|
239
|
+
require('core-js/es/reflect');
|
|
240
|
+
require('core-js/proposals/reflect-metadata');
|
|
241
|
+
```
|
|
242
|
+
Note that this might also be related to other issues with the dependency injection and parameter type reflection.
|
|
243
|
+
|
|
232
244
|
### @Input() bindings are not reflected into fixture when `ChangeDetectionStrategy.OnPush` is used
|
|
233
245
|
|
|
234
246
|
This issue is not related to Jest, [it's a known Angular bug](https://github.com/angular/angular/issues/12313)
|
|
@@ -303,16 +315,19 @@ Override `globals` object in Jest config:
|
|
|
303
315
|
"jest": {
|
|
304
316
|
"globals": {
|
|
305
317
|
"ts-jest": {
|
|
306
|
-
"tsConfig": "<rootDir>/
|
|
318
|
+
"tsConfig": "<rootDir>/tsconfig.custom.json",
|
|
307
319
|
"stringifyContentPathRegex": "\\.html$",
|
|
308
|
-
"astTransformers": [
|
|
320
|
+
"astTransformers": [
|
|
321
|
+
"jest-preset-angular/build/InlineFilesTransformer",
|
|
322
|
+
"jest-preset-angular/build/StripStylesTransformer"
|
|
323
|
+
],
|
|
309
324
|
}
|
|
310
325
|
}
|
|
311
326
|
}
|
|
312
327
|
}
|
|
313
328
|
```
|
|
314
329
|
|
|
315
|
-
If you choose to overide `globals` in order to point at a specific tsconfig, you will need to add `
|
|
330
|
+
If you choose to overide `globals` in order to point at a specific tsconfig, you will need to add the `astTransformers` to the `globals.ts-jest` section too, otherwise you will get parse errors on any html templates.
|
|
316
331
|
|
|
317
332
|
### Unexpected token [import|export|other]
|
|
318
333
|
|
|
@@ -367,7 +382,7 @@ A default `tsconfig.spec.json` after modifying will look like this
|
|
|
367
382
|
}
|
|
368
383
|
```
|
|
369
384
|
|
|
370
|
-
By default Jest doesn't transform `node_modules`, because they should be valid JavaScript files. However, it happens that library authors assume that you'll compile their sources. So you have to tell this to Jest explicitly. Above snippet means that `@ngrx`, `angular2-ui-switch` and `ng-dynamic` will be
|
|
385
|
+
By default Jest doesn't transform `node_modules`, because they should be valid JavaScript files. However, it happens that library authors assume that you'll compile their sources. So you have to tell this to Jest explicitly. Above snippet means that `@ngrx`, `angular2-ui-switch` and `ng-dynamic` will be transformed, even though they're `node_modules`.
|
|
371
386
|
|
|
372
387
|
#### Allow JS files in your TS `compilerOptions`
|
|
373
388
|
|
|
@@ -385,7 +400,9 @@ This tells `ts-jest` (a preprocessor this preset using to transform TS files) to
|
|
|
385
400
|
|
|
386
401
|
Some vendors publish their sources without transpiling. You need to say jest to transpile such files manually since `typescript` (and thus `ts-jest` used by this preset) do not transpile them.
|
|
387
402
|
|
|
388
|
-
1. Install
|
|
403
|
+
1. Install dependencies required by Jest official documentation for [Babel integration](https://jest-bot.github.io/jest/docs/babel.html).
|
|
404
|
+
|
|
405
|
+
2. Install `@babel/preset-env` and add `babel.config.js` (or modify existing if needed) with the following content:
|
|
389
406
|
```js
|
|
390
407
|
module.exports = function(api) {
|
|
391
408
|
api.cache(true);
|
|
@@ -403,13 +420,13 @@ module.exports = function(api) {
|
|
|
403
420
|
|
|
404
421
|
*Note: do not use a `.babelrc` file otherwise the packages that you specify in the next step will not be picked up. CF [Babel documentation](https://babeljs.io/docs/en/configuration#what-s-your-use-case) and the comment `You want to compile node_modules? babel.config.js is for you!`*.
|
|
405
422
|
|
|
406
|
-
|
|
423
|
+
3. Update Jest configuration (by default TypeScript process untranspiled JS files which is source of the problem):
|
|
407
424
|
|
|
408
425
|
```js
|
|
409
426
|
{
|
|
410
427
|
"jest": {
|
|
411
428
|
"transform": {
|
|
412
|
-
"^.+\\.(ts|html)$": "
|
|
429
|
+
"^.+\\.(ts|html)$": "ts-jest",
|
|
413
430
|
"^.+\\.js$": "babel-jest"
|
|
414
431
|
},
|
|
415
432
|
}
|
|
@@ -456,7 +473,7 @@ Reference: https://github.com/facebook/jest/issues/708
|
|
|
456
473
|
|
|
457
474
|
### Failing with Node v7 or lower
|
|
458
475
|
|
|
459
|
-
By default we use JSDOM
|
|
476
|
+
By default we use JSDOM v15, which requires Node v8+. If you want to use Node in a lower version to run your tests, make sure to configure jest to use an older JSDOM version, either in your `jest.config.js`, `jest.config.json` or `package.json`:
|
|
460
477
|
|
|
461
478
|
```json
|
|
462
479
|
"testEnvironment": "jsdom"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
|
3
|
+
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
|
4
|
+
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
|
5
|
+
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
|
6
|
+
r[k] = a[j];
|
|
7
|
+
return r;
|
|
8
|
+
};
|
|
9
|
+
var jestDOMElementSerializer = require('pretty-format').plugins.DOMElement;
|
|
10
|
+
var attributesToRemovePatterns = ['ng-reflect', '_nghost', '_ngcontent', 'ng-version'];
|
|
11
|
+
var hasAttributesToRemove = function (attribute) {
|
|
12
|
+
return attributesToRemovePatterns
|
|
13
|
+
.some(function (removePattern) { return attribute.name.startsWith(removePattern); });
|
|
14
|
+
};
|
|
15
|
+
var serialize = function (node) {
|
|
16
|
+
var rest = [];
|
|
17
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
18
|
+
rest[_i - 1] = arguments[_i];
|
|
19
|
+
}
|
|
20
|
+
var nodeCopy = node.cloneNode(true);
|
|
21
|
+
Object.values(nodeCopy.attributes)
|
|
22
|
+
.filter(hasAttributesToRemove)
|
|
23
|
+
.forEach(function (attribute) { return nodeCopy.attributes.removeNamedItem(attribute.name); });
|
|
24
|
+
return jestDOMElementSerializer.serialize.apply(jestDOMElementSerializer, __spreadArrays([nodeCopy], rest));
|
|
25
|
+
};
|
|
26
|
+
var serializeTestFn = function (val) {
|
|
27
|
+
return val.attributes !== undefined && Object.values(val.attributes)
|
|
28
|
+
.some(hasAttributesToRemove);
|
|
29
|
+
};
|
|
30
|
+
var test = function (val) {
|
|
31
|
+
return jestDOMElementSerializer.test(val) && serializeTestFn(val);
|
|
32
|
+
};
|
|
33
|
+
module.exports = {
|
|
34
|
+
serialize: serialize,
|
|
35
|
+
test: test
|
|
36
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var printAttributes = function (val, attributes, print, indent, colors, opts) {
|
|
3
|
+
return attributes
|
|
4
|
+
.sort()
|
|
5
|
+
.map(function (attribute) {
|
|
6
|
+
return (opts.spacing +
|
|
7
|
+
indent(colors.prop.open + attribute + colors.prop.close + '=') +
|
|
8
|
+
colors.value.open +
|
|
9
|
+
(val.componentInstance[attribute] &&
|
|
10
|
+
val.componentInstance[attribute].constructor
|
|
11
|
+
? '{[Function ' +
|
|
12
|
+
val.componentInstance[attribute].constructor.name +
|
|
13
|
+
']}'
|
|
14
|
+
: "\"" + val.componentInstance[attribute] + "\"") +
|
|
15
|
+
colors.value.close);
|
|
16
|
+
})
|
|
17
|
+
.join('');
|
|
18
|
+
};
|
|
19
|
+
var print = function (val, print, indent, opts, colors) {
|
|
20
|
+
var componentAttrs = '';
|
|
21
|
+
var componentName = val.componentRef._elDef.element.name;
|
|
22
|
+
var nodes = (val.componentRef._view.nodes || [])
|
|
23
|
+
.filter(function (node) { return node && node.hasOwnProperty('renderElement'); })
|
|
24
|
+
.map(function (node) { return Array.from(node.renderElement.childNodes).map(print).join(''); })
|
|
25
|
+
.join(opts.edgeSpacing);
|
|
26
|
+
var attributes = Object.keys(val.componentInstance);
|
|
27
|
+
if (attributes.length) {
|
|
28
|
+
componentAttrs += printAttributes(val, attributes, print, indent, colors, opts);
|
|
29
|
+
}
|
|
30
|
+
return ('<' +
|
|
31
|
+
componentName +
|
|
32
|
+
componentAttrs +
|
|
33
|
+
(componentAttrs.length ? '\n' : '') +
|
|
34
|
+
'>\n' +
|
|
35
|
+
indent(nodes) +
|
|
36
|
+
'\n</' +
|
|
37
|
+
componentName +
|
|
38
|
+
'>');
|
|
39
|
+
};
|
|
40
|
+
var test = function (val) {
|
|
41
|
+
return val !== undefined &&
|
|
42
|
+
val !== null &&
|
|
43
|
+
typeof val === 'object' &&
|
|
44
|
+
Object.prototype.hasOwnProperty.call(val, 'componentRef');
|
|
45
|
+
};
|
|
46
|
+
module.exports = {
|
|
47
|
+
print: print,
|
|
48
|
+
test: test
|
|
49
|
+
};
|
|
@@ -6,20 +6,17 @@
|
|
|
6
6
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
7
7
|
*
|
|
8
8
|
*/
|
|
9
|
-
|
|
10
9
|
'use strict';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const print = () => '';
|
|
21
|
-
|
|
10
|
+
var HTML_ELEMENT_REGEXP = /Comment/;
|
|
11
|
+
var test = function (value) {
|
|
12
|
+
return value !== undefined &&
|
|
13
|
+
value !== null &&
|
|
14
|
+
value.nodeType === 8 &&
|
|
15
|
+
value.constructor !== undefined &&
|
|
16
|
+
HTML_ELEMENT_REGEXP.test(value.constructor.name);
|
|
17
|
+
};
|
|
18
|
+
var print = function () { return ''; };
|
|
22
19
|
module.exports = {
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
print: print,
|
|
21
|
+
test: test
|
|
25
22
|
};
|
|
@@ -5,25 +5,27 @@
|
|
|
5
5
|
*
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
var TransformUtils_1 = require("./TransformUtils");
|
|
9
|
+
// replace original ts-jest ConfigSet with this simple interface, as it would require
|
|
10
|
+
// jest-preset-angular to add several babel devDependencies to get the other types
|
|
11
|
+
// inside the ConfigSet right
|
|
8
12
|
/** Angular component decorator TemplateUrl property name */
|
|
9
13
|
var TEMPLATE_URL = 'templateUrl';
|
|
10
14
|
/** Angular component decorator StyleUrls property name */
|
|
11
15
|
var STYLE_URLS = 'styleUrls';
|
|
12
|
-
/** Angular component decorator Styles property name */
|
|
13
|
-
var STYLES = 'styles';
|
|
14
16
|
/** Angular component decorator Template property name */
|
|
15
17
|
var TEMPLATE = 'template';
|
|
16
18
|
/** Node require function name */
|
|
17
19
|
var REQUIRE = 'require';
|
|
18
20
|
/**
|
|
19
|
-
* Property names
|
|
21
|
+
* Property names anywhere in an angular project to transform
|
|
20
22
|
*/
|
|
21
|
-
var TRANSFORM_PROPS = [TEMPLATE_URL,
|
|
23
|
+
var TRANSFORM_PROPS = [TEMPLATE_URL, STYLE_URLS];
|
|
22
24
|
/**
|
|
23
25
|
* Transformer ID
|
|
24
26
|
* @internal
|
|
25
27
|
*/
|
|
26
|
-
exports.name = 'angular-component-inline-
|
|
28
|
+
exports.name = 'angular-component-inline-files';
|
|
27
29
|
// increment this each time the code is modified
|
|
28
30
|
/**
|
|
29
31
|
* Transformer Version
|
|
@@ -39,14 +41,15 @@ function factory(cs) {
|
|
|
39
41
|
* Our compiler (typescript, or a module with typescript-like interface)
|
|
40
42
|
*/
|
|
41
43
|
var ts = cs.compilerModule;
|
|
44
|
+
var createStringLiteral = TransformUtils_1.getCreateStringLiteral(ts);
|
|
42
45
|
/**
|
|
43
|
-
* Traverses the AST down to the relevant assignments in the
|
|
44
|
-
*
|
|
46
|
+
* Traverses the AST down to the relevant assignments anywhere in the file
|
|
47
|
+
* and returns a boolean indicating if it should be transformed.
|
|
45
48
|
*/
|
|
46
49
|
function isPropertyAssignmentToTransform(node) {
|
|
47
|
-
return ts.isPropertyAssignment(node) &&
|
|
50
|
+
return (ts.isPropertyAssignment(node) &&
|
|
48
51
|
ts.isIdentifier(node.name) &&
|
|
49
|
-
TRANSFORM_PROPS.includes(node.name.text);
|
|
52
|
+
TRANSFORM_PROPS.includes(node.name.text));
|
|
50
53
|
}
|
|
51
54
|
/**
|
|
52
55
|
* Clones the assignment and manipulates it depending on its name.
|
|
@@ -57,29 +60,29 @@ function factory(cs) {
|
|
|
57
60
|
var assignmentNameText = mutableAssignment.name.text;
|
|
58
61
|
switch (assignmentNameText) {
|
|
59
62
|
case TEMPLATE_URL:
|
|
60
|
-
//
|
|
61
|
-
|
|
63
|
+
// replace 'templateUrl' with 'template'
|
|
64
|
+
// reuse the right-hand-side literal (the filepath) from the assignment
|
|
65
|
+
var pathLiteral = mutableAssignment.initializer;
|
|
62
66
|
// fix templatePathLiteral if it was a non-relative path
|
|
63
|
-
if (ts.isStringLiteral(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
templatePathLiteral = ts.createStringLiteral("./" + templatePathStringLiteral.text);
|
|
67
|
+
if (ts.isStringLiteral(pathLiteral)) {
|
|
68
|
+
// match if it does not start with ./ or ../ or /
|
|
69
|
+
if (pathLiteral.text &&
|
|
70
|
+
!pathLiteral.text.match(/^(\.\/|\.\.\/|\/)/)) {
|
|
71
|
+
// make path relative by prepending './'
|
|
72
|
+
pathLiteral = createStringLiteral("./" + pathLiteral.text);
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
|
-
// replace 'templateUrl' with 'template'
|
|
73
|
-
mutableAssignment.name = ts.createIdentifier(TEMPLATE);
|
|
74
75
|
// replace current initializer with require(path)
|
|
75
|
-
|
|
76
|
+
var requireCall = ts.createCall(
|
|
76
77
|
/* expression */ ts.createIdentifier(REQUIRE),
|
|
77
78
|
/* type arguments */ undefined,
|
|
78
|
-
/* arguments array */ [
|
|
79
|
+
/* arguments array */ [pathLiteral]);
|
|
80
|
+
mutableAssignment.name = ts.createIdentifier(TEMPLATE);
|
|
81
|
+
mutableAssignment.initializer = requireCall;
|
|
79
82
|
break;
|
|
80
|
-
case STYLES:
|
|
81
83
|
case STYLE_URLS:
|
|
82
|
-
// replace
|
|
84
|
+
// replace styleUrls value with emtpy array
|
|
85
|
+
// inlining all urls would be way more complicated and slower
|
|
83
86
|
mutableAssignment.initializer = ts.createArrayLiteral();
|
|
84
87
|
break;
|
|
85
88
|
}
|
|
@@ -96,24 +99,20 @@ function factory(cs) {
|
|
|
96
99
|
* @param node The node to be visited
|
|
97
100
|
*/
|
|
98
101
|
var visitor = function (node) {
|
|
99
|
-
var resultNode;
|
|
102
|
+
var resultNode = node;
|
|
100
103
|
// before we create a deep clone to modify, we make sure that
|
|
101
104
|
// this is an assignment which we want to transform
|
|
102
105
|
if (isPropertyAssignmentToTransform(node)) {
|
|
103
106
|
// get transformed node with changed properties
|
|
104
107
|
resultNode = transfromPropertyAssignmentForJest(node);
|
|
105
108
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
resultNode = ts.visitEachChild(node, visitor, ctx);
|
|
109
|
-
}
|
|
109
|
+
// look for interesting assignments inside this node in any case
|
|
110
|
+
resultNode = ts.visitEachChild(resultNode, visitor, ctx);
|
|
110
111
|
// finally return the currently visited node
|
|
111
112
|
return resultNode;
|
|
112
113
|
};
|
|
113
114
|
return visitor;
|
|
114
115
|
}
|
|
115
|
-
return function (ctx) {
|
|
116
|
-
return function (sf) { return ts.visitNode(sf, createVisitor(ctx, sf)); };
|
|
117
|
-
};
|
|
116
|
+
return function (ctx) { return function (sf) { return ts.visitNode(sf, createVisitor(ctx, sf)); }; };
|
|
118
117
|
}
|
|
119
118
|
exports.factory = factory;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Code is inspired by
|
|
4
|
+
* https://github.com/kulshekhar/ts-jest/blob/25e1c63dd3797793b0f46fa52fdee580b46f66ae/src/transformers/hoist-jest.ts
|
|
5
|
+
*
|
|
6
|
+
*
|
|
7
|
+
* IMPLEMENTATION DETAILS:
|
|
8
|
+
* This transformer handles one concern: removing styles.
|
|
9
|
+
*
|
|
10
|
+
* The property 'styles' inside a @Component(...) Decorator argument will
|
|
11
|
+
* be modified, even if they are not used in the context of an
|
|
12
|
+
* Angular Component.
|
|
13
|
+
*
|
|
14
|
+
* This is the required AST to trigger the transformation:
|
|
15
|
+
*
|
|
16
|
+
* ClassDeclaration
|
|
17
|
+
* Decorator
|
|
18
|
+
* CallExpression
|
|
19
|
+
* ObjectLiteralExpression
|
|
20
|
+
* PropertyAssignment
|
|
21
|
+
* Identifier
|
|
22
|
+
* StringLiteral
|
|
23
|
+
*/
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
/** Angular component decorator Styles property name */
|
|
26
|
+
var STYLES = 'styles';
|
|
27
|
+
/** Angular component decorator name */
|
|
28
|
+
var COMPONENT = 'Component';
|
|
29
|
+
/** All props to be transformed inside a decorator */
|
|
30
|
+
var TRANSFORM_IN_DECORATOR_PROPS = [STYLES];
|
|
31
|
+
/**
|
|
32
|
+
* Transformer ID
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
exports.name = 'angular-component-strip-styles';
|
|
36
|
+
// increment this each time the code is modified
|
|
37
|
+
/**
|
|
38
|
+
* Transformer Version
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
exports.version = 1;
|
|
42
|
+
/**
|
|
43
|
+
* The factory of hoisting transformer factory
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
function factory(cs) {
|
|
47
|
+
/**
|
|
48
|
+
* Our compiler (typescript, or a module with typescript-like interface)
|
|
49
|
+
*/
|
|
50
|
+
var ts = cs.compilerModule;
|
|
51
|
+
/**
|
|
52
|
+
* Traverses the AST down inside a decorator to a styles assignment
|
|
53
|
+
* and returns a boolean indicating if it should be transformed.
|
|
54
|
+
*/
|
|
55
|
+
function isInDecoratorPropertyAssignmentToTransform(node) {
|
|
56
|
+
return getInDecoratorPropertyAssignmentsToTransform(node).length > 0;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Traverses the AST down inside a decorator to a styles assignment
|
|
60
|
+
* returns it in an array.
|
|
61
|
+
*/
|
|
62
|
+
function getInDecoratorPropertyAssignmentsToTransform(node) {
|
|
63
|
+
if (!ts.isClassDeclaration(node) || !node.decorators) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
return node.decorators
|
|
67
|
+
.map(function (dec) { return dec.expression; })
|
|
68
|
+
.filter(ts.isCallExpression)
|
|
69
|
+
.filter(function (callExpr) {
|
|
70
|
+
return ts.isIdentifier(callExpr.expression) && callExpr.expression.getText() === COMPONENT;
|
|
71
|
+
})
|
|
72
|
+
.reduce(function (acc, nxtCallExpr) { return Array.prototype.concat.apply(acc, nxtCallExpr.arguments
|
|
73
|
+
.filter(ts.isObjectLiteralExpression)
|
|
74
|
+
.reduce(function (acc, nxtArg) { return Array.prototype.concat.apply(acc, nxtArg.properties
|
|
75
|
+
.filter(ts.isPropertyAssignment)
|
|
76
|
+
.filter(function (propAss) {
|
|
77
|
+
return ts.isIdentifier(propAss.name) &&
|
|
78
|
+
TRANSFORM_IN_DECORATOR_PROPS.includes(propAss.name.text);
|
|
79
|
+
})); }, [])); }, []);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Clones the styles assignment and manipulates it.
|
|
83
|
+
* @param node the property assignment to change
|
|
84
|
+
*/
|
|
85
|
+
function transformStylesAssignmentForJest(node) {
|
|
86
|
+
var mutableNode = ts.getMutableClone(node);
|
|
87
|
+
var assignments = getInDecoratorPropertyAssignmentsToTransform(mutableNode);
|
|
88
|
+
assignments.forEach(function (assignment) {
|
|
89
|
+
if (assignment.name.text === STYLES) {
|
|
90
|
+
// replace initializer array with empty array
|
|
91
|
+
assignment.initializer = ts.createArrayLiteral();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
return mutableNode;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Create a source file visitor which will visit all nodes in a source file
|
|
98
|
+
* @param ctx The typescript transformation context
|
|
99
|
+
* @param _ The owning source file
|
|
100
|
+
*/
|
|
101
|
+
function createVisitor(ctx, _) {
|
|
102
|
+
/**
|
|
103
|
+
* Main visitor, which will be called recursively for each node in the source file's AST
|
|
104
|
+
* @param node The node to be visited
|
|
105
|
+
*/
|
|
106
|
+
var visitor = function (node) {
|
|
107
|
+
// before we create a deep clone to modify, we make sure that
|
|
108
|
+
// this is an assignment which we want to transform
|
|
109
|
+
if (isInDecoratorPropertyAssignmentToTransform(node)) {
|
|
110
|
+
// get transformed node with changed properties
|
|
111
|
+
return transformStylesAssignmentForJest(node);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// else look for assignments inside this node recursively
|
|
115
|
+
return ts.visitEachChild(node, visitor, ctx);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
return visitor;
|
|
119
|
+
}
|
|
120
|
+
return function (ctx) { return function (sf) { return ts.visitNode(sf, createVisitor(ctx, sf)); }; };
|
|
121
|
+
}
|
|
122
|
+
exports.factory = factory;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/**
|
|
4
|
+
* returns the compiler function to create a string literal. If an old version
|
|
5
|
+
* of the TypeScript module is used, it will create a function that replaces the
|
|
6
|
+
* behavior of the `createStringLiteral` function.
|
|
7
|
+
* @param ts TypeScript compiler module
|
|
8
|
+
*/
|
|
9
|
+
function getCreateStringLiteral(ts) {
|
|
10
|
+
if (ts.createStringLiteral && typeof ts.createStringLiteral === 'function') {
|
|
11
|
+
return ts.createStringLiteral;
|
|
12
|
+
}
|
|
13
|
+
return function createStringLiteral(text) {
|
|
14
|
+
var node = (ts.createNode(ts.SyntaxKind.StringLiteral, -1, -1));
|
|
15
|
+
node.text = text;
|
|
16
|
+
node.flags |= ts.NodeFlags.Synthesized;
|
|
17
|
+
return node;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
exports.getCreateStringLiteral = getCreateStringLiteral;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var METADATA_KEY_PARAMTYPES = "design:paramtypes";
|
|
3
|
+
var CTOR_PARAMETERS_JPA = "ctorParametersJPA";
|
|
4
|
+
// weird workaround to avoid 'ReferenceError: globalThis is not defined' in node version < 11
|
|
5
|
+
global.globalThis = global.globalThis || undefined;
|
|
6
|
+
var _global = globalThis || global; // globalThis available since node v12/TS v3.4
|
|
7
|
+
var reflect = _global["Reflect"]; // reflect type in global has not these methods
|
|
8
|
+
// let's not blindly override, maybe there is already a reflect lib in use
|
|
9
|
+
// but just overriding one of the two functions does not serve any purpose
|
|
10
|
+
if (!reflect.metadata && !reflect.getOwnMetadata) {
|
|
11
|
+
reflect.metadata = function (metadataKey, metadataValue) { return function (target, key) {
|
|
12
|
+
if (metadataKey === METADATA_KEY_PARAMTYPES && key === undefined) { // key undefined is ctor
|
|
13
|
+
target[CTOR_PARAMETERS_JPA] = metadataValue;
|
|
14
|
+
}
|
|
15
|
+
}; };
|
|
16
|
+
reflect.getOwnMetadata = function (metadata, target, key) {
|
|
17
|
+
if (metadata === METADATA_KEY_PARAMTYPES && key === undefined) { // key undefined is ctor
|
|
18
|
+
return target[CTOR_PARAMETERS_JPA];
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
require('./reflectMetadata');
|
|
3
|
+
require('zone.js/dist/zone.js');
|
|
4
|
+
require('zone.js/dist/proxy.js');
|
|
5
|
+
require('zone.js/dist/sync-test');
|
|
6
|
+
require('zone.js/dist/async-test');
|
|
7
|
+
require('zone.js/dist/fake-async-test');
|
|
8
|
+
require('./zone-patch');
|
|
9
|
+
var getTestBed = require('@angular/core/testing').getTestBed;
|
|
10
|
+
var BrowserDynamicTestingModule = require('@angular/platform-browser-dynamic/testing').BrowserDynamicTestingModule;
|
|
11
|
+
var platformBrowserDynamicTesting = require('@angular/platform-browser-dynamic/testing').platformBrowserDynamicTesting;
|
|
12
|
+
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
|