jest-preset-angular 8.2.0 → 8.3.2
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/AngularNoNgAttributesSnapshotSerializer.js +57 -0
- package/AngularSnapshotSerializer.js +79 -0
- package/HTMLCommentSerializer.js +25 -0
- package/README.md +29 -23
- package/build/AngularNoNgAttributesSnapshotSerializer.js +6 -13
- package/build/AngularSnapshotSerializer.js +5 -19
- package/build/HTMLCommentSerializer.js +1 -9
- package/build/InlineFilesTransformer.js +9 -71
- package/build/StripStylesTransformer.js +13 -76
- package/build/TransformUtils.js +2 -7
- package/build/reflect-metadata.js +18 -0
- package/build/setup-jest.js +18 -0
- package/build/zone-patch/index.js +1 -16
- package/index.js +1 -1
- package/jest-preset.js +7 -5
- package/package.json +6 -24
- package/zone-patch/README.md +6 -0
- package/zone-patch/index.js +136 -0
- package/.circleci/config.yml +0 -75
- package/CHANGELOG.md +0 -218
- package/LICENSE +0 -21
- package/build/reflectMetadata.js +0 -21
- package/build/setupJest.js +0 -12
- package/greenkeeper.json +0 -10
- package/tsconfig.json +0 -15
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const jestDOMElementSerializer = require('pretty-format').plugins.DOMElement;
|
|
4
|
+
|
|
5
|
+
const attributesToRemovePatterns = ['ng-reflect', '_nghost', '_ngcontent', 'ng-version'];
|
|
6
|
+
const attributesToClean = {
|
|
7
|
+
class: [/^(?:mat|cdk|ng).*-\w*\d+-\d+$/, /^ng-star-inserted$/], // e.g. "ng-tns-c25-1" or "ng-star-inserted", literally
|
|
8
|
+
id: [/^(?:mat|cdk|ng).*-\d+$/], // e.g. "mat-input-4", "cdk-step-content-0-0"
|
|
9
|
+
for: [/^(?:mat|cdk|ng).*-\d+$/], // e.g. "mat-form-field-label-9"
|
|
10
|
+
'aria-owns': [/^(?:mat|cdk|ng).*-\d+$/], // e.g. "mat-input-4"
|
|
11
|
+
'aria-labelledby': [/^(?:mat|cdk|ng).*-\d+$/], // e.g. "mat-input-4", "cdk-step-label-0-0"
|
|
12
|
+
'aria-controls': [/^(?:mat|cdk|ng).*-\d+$/], // e.g. "cdk-step-content-2-0"
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const hasAttributesToRemove = (attribute) =>
|
|
16
|
+
attributesToRemovePatterns.some((removePattern) => attribute.name.startsWith(removePattern));
|
|
17
|
+
const hasAttributesToClean = (attribute) =>
|
|
18
|
+
Object.keys(attributesToClean).some((removePatternKey) => attribute.name === removePatternKey);
|
|
19
|
+
|
|
20
|
+
const serialize = (node, ...rest) => {
|
|
21
|
+
const nodeCopy = node.cloneNode(true);
|
|
22
|
+
// Remove angular-specific attributes
|
|
23
|
+
Object.values(nodeCopy.attributes)
|
|
24
|
+
.filter(hasAttributesToRemove)
|
|
25
|
+
.forEach((attribute) => nodeCopy.attributes.removeNamedItem(attribute.name));
|
|
26
|
+
// Remove angular auto-added classes
|
|
27
|
+
Object.values(nodeCopy.attributes)
|
|
28
|
+
.filter(hasAttributesToClean)
|
|
29
|
+
.forEach((attribute) => {
|
|
30
|
+
attribute.value = attribute.value
|
|
31
|
+
.split(' ')
|
|
32
|
+
.filter(
|
|
33
|
+
(attrValue) =>
|
|
34
|
+
!attributesToClean[attribute.name].some((attributeCleanRegex) => attributeCleanRegex.test(attrValue))
|
|
35
|
+
)
|
|
36
|
+
.join(' ');
|
|
37
|
+
if (attribute.value === '') {
|
|
38
|
+
nodeCopy.attributes.removeNamedItem(attribute.name);
|
|
39
|
+
} else {
|
|
40
|
+
nodeCopy.attributes.setNamedItem(attribute);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return jestDOMElementSerializer.serialize(nodeCopy, ...rest);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const serializeTestFn = (val) =>
|
|
48
|
+
val.attributes !== undefined &&
|
|
49
|
+
Object.values(val.attributes).some(
|
|
50
|
+
(attribute) => hasAttributesToRemove(attribute) || hasAttributesToClean(attribute)
|
|
51
|
+
);
|
|
52
|
+
const test = (val) => jestDOMElementSerializer.test(val) && serializeTestFn(val);
|
|
53
|
+
|
|
54
|
+
module.exports = {
|
|
55
|
+
serialize,
|
|
56
|
+
test,
|
|
57
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const printAttributes = (val, attributes, print, indent, colors, opts) => {
|
|
4
|
+
return attributes
|
|
5
|
+
.sort()
|
|
6
|
+
.map((attribute) => {
|
|
7
|
+
return (
|
|
8
|
+
opts.spacing +
|
|
9
|
+
indent(colors.prop.open + attribute + colors.prop.close + '=') +
|
|
10
|
+
colors.value.open +
|
|
11
|
+
(val.componentInstance[attribute] && val.componentInstance[attribute].constructor
|
|
12
|
+
? '{[Function ' + val.componentInstance[attribute].constructor.name + ']}'
|
|
13
|
+
: `"${val.componentInstance[attribute]}"`) +
|
|
14
|
+
colors.value.close
|
|
15
|
+
);
|
|
16
|
+
})
|
|
17
|
+
.join('');
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const ivyEnabled = () => {
|
|
21
|
+
// Should be required lazily, since it will throw an exception
|
|
22
|
+
// `Cannot resolve parameters...`.
|
|
23
|
+
const { ɵivyEnabled } = require('@angular/core');
|
|
24
|
+
|
|
25
|
+
return !!ɵivyEnabled;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Ivy component definition was stored on the `ngComponentDef`
|
|
29
|
+
// property before `9.0.0-next.10`. Since `9.0.0-next.10` it was
|
|
30
|
+
// renamed to `ɵcmp`.
|
|
31
|
+
const getComponentDef = (type) => type.ngComponentDef || type.ɵcmp;
|
|
32
|
+
|
|
33
|
+
const print = (fixture, print, indent, opts, colors) => {
|
|
34
|
+
let nodes = '';
|
|
35
|
+
let componentAttrs = '';
|
|
36
|
+
let componentName = '';
|
|
37
|
+
|
|
38
|
+
if (ivyEnabled()) {
|
|
39
|
+
const componentDef = getComponentDef(fixture.componentRef.componentType);
|
|
40
|
+
componentName = componentDef.selectors[0][0];
|
|
41
|
+
nodes = Array.from(fixture.componentRef.location.nativeElement.childNodes).map(print).join('');
|
|
42
|
+
} else {
|
|
43
|
+
componentName = fixture.componentRef._elDef.element.name;
|
|
44
|
+
nodes = (fixture.componentRef._view.nodes || [])
|
|
45
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
46
|
+
.filter((node) => node && node.hasOwnProperty('renderElement'))
|
|
47
|
+
.map((node) => Array.from(node.renderElement.childNodes).map(print).join(''))
|
|
48
|
+
.join(opts.edgeSpacing);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const attributes = Object.keys(fixture.componentInstance);
|
|
52
|
+
|
|
53
|
+
if (attributes.length) {
|
|
54
|
+
componentAttrs += printAttributes(fixture, attributes, print, indent, colors, opts);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
'<' +
|
|
59
|
+
componentName +
|
|
60
|
+
componentAttrs +
|
|
61
|
+
(componentAttrs.length ? '\n' : '') +
|
|
62
|
+
'>\n' +
|
|
63
|
+
indent(nodes) +
|
|
64
|
+
'\n</' +
|
|
65
|
+
componentName +
|
|
66
|
+
'>'
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const test = (val) =>
|
|
71
|
+
val !== undefined &&
|
|
72
|
+
val !== null &&
|
|
73
|
+
typeof val === 'object' &&
|
|
74
|
+
Object.prototype.hasOwnProperty.call(val, 'componentRef');
|
|
75
|
+
|
|
76
|
+
module.exports = {
|
|
77
|
+
print: print,
|
|
78
|
+
test: test,
|
|
79
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the BSD-style license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
|
6
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const HTML_ELEMENT_REGEXP = /Comment/;
|
|
13
|
+
const test = (value) =>
|
|
14
|
+
value !== undefined &&
|
|
15
|
+
value !== null &&
|
|
16
|
+
value.nodeType === 8 &&
|
|
17
|
+
value.constructor !== undefined &&
|
|
18
|
+
HTML_ELEMENT_REGEXP.test(value.constructor.name);
|
|
19
|
+
|
|
20
|
+
const print = () => '';
|
|
21
|
+
|
|
22
|
+
module.exports = {
|
|
23
|
+
print: print,
|
|
24
|
+
test: test,
|
|
25
|
+
};
|
package/README.md
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://circleci.com/gh/thymikee/jest-preset-angular)
|
|
4
4
|
[](https://www.npmjs.com/package/jest-preset-angular) [](https://greenkeeper.io/)
|
|
5
|
+

|
|
5
6
|
|
|
6
7
|
A preset of [Jest](http://facebook.github.io/jest) configuration for [Angular](https://angular.io/) projects.
|
|
7
8
|
|
|
8
9
|
This is a part of the article: [Testing Angular faster with Jest](https://www.xfive.co/blog/testing-angular-faster-jest/).
|
|
9
10
|
|
|
10
|
-
_Note: This preset does not
|
|
11
|
+
_Note: This preset does not support 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)._
|
|
11
12
|
|
|
12
13
|
## Installation
|
|
13
14
|
|
|
@@ -21,14 +22,14 @@ This will install `jest`, `@types/jest`, `ts-jest` as dependencies needed to run
|
|
|
21
22
|
|
|
22
23
|
## Usage
|
|
23
24
|
|
|
24
|
-
In `src` directory create `
|
|
25
|
+
In `src` directory create `setup-jest.ts` file with following contents:
|
|
25
26
|
|
|
26
27
|
```ts
|
|
27
28
|
import 'jest-preset-angular';
|
|
28
|
-
import './
|
|
29
|
+
import './jest-global-mocks'; // browser mocks globally available for every test
|
|
29
30
|
```
|
|
30
31
|
|
|
31
|
-
_Note: feel free to copy the [`
|
|
32
|
+
_Note: feel free to copy the [`jest-global-mocks.ts`](https://github.com/thymikee/jest-preset-angular/blob/master/e2e/test-app-v9/jest-global-mocks.ts) file from the test app directory and save it next to the `setup-jest.ts` file._
|
|
32
33
|
|
|
33
34
|
...and include this in your `package.json`:
|
|
34
35
|
|
|
@@ -36,7 +37,7 @@ _Note: feel free to copy the [`jestGlobalMocks.ts`](https://github.com/thymikee/
|
|
|
36
37
|
{
|
|
37
38
|
"jest": {
|
|
38
39
|
"preset": "jest-preset-angular",
|
|
39
|
-
"setupFilesAfterEnv": ["<rootDir>/src/
|
|
40
|
+
"setupFilesAfterEnv": ["<rootDir>/src/setup-jest.ts"]
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
```
|
|
@@ -51,12 +52,14 @@ By Angular CLI defaults you'll have a `src/test.ts` file which will be picked up
|
|
|
51
52
|
module.exports = {
|
|
52
53
|
globals: {
|
|
53
54
|
'ts-jest': {
|
|
54
|
-
|
|
55
|
+
tsconfig: '<rootDir>/tsconfig.spec.json',
|
|
55
56
|
stringifyContentPathRegex: '\\.html$',
|
|
56
|
-
astTransformers:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
astTransformers: {
|
|
58
|
+
before: [
|
|
59
|
+
'jest-preset-angular/build/InlineFilesTransformer',
|
|
60
|
+
'jest-preset-angular/build/StripStylesTransformer',
|
|
61
|
+
],
|
|
62
|
+
},
|
|
60
63
|
},
|
|
61
64
|
},
|
|
62
65
|
transform: {
|
|
@@ -87,7 +90,7 @@ module.exports = {
|
|
|
87
90
|
- `"moduleNameMapper"` – if you're using absolute imports here's how to tell Jest where to look for them; uses regex
|
|
88
91
|
- `"setupFilesAfterEnv"` – this is the heart of our config, in this file we'll setup and patch environment within tests are running
|
|
89
92
|
- `"transformIgnorePatterns"` – unfortunately some modules (like @ngrx) are released as TypeScript files, not pure JavaScript; in such cases we cannot ignore them (all node_modules are ignored by default), so they can be transformed through TS compiler like any other module in our project.
|
|
90
|
-
- `"snapshotSerializers"` - array of serializers which will be applied to snapshot the code. Note: by default angular adds some angular-specific attributes to the code (like `ng-reflect-*`, `ng-version="*"`, `_ngcontent-c*` etc). This package provides serializer to remove such attributes. This makes snapshots cleaner and more human-readable. To remove such specific attributes use `AngularNoNgAttributesSnapshotSerializer` serializer. You need to add `AngularNoNgAttributesSnapshotSerializer` serializer manually (see [`
|
|
93
|
+
- `"snapshotSerializers"` - array of serializers which will be applied to snapshot the code. Note: by default angular adds some angular-specific attributes to the code (like `ng-reflect-*`, `ng-version="*"`, `_ngcontent-c*` etc). This package provides serializer to remove such attributes. This makes snapshots cleaner and more human-readable. To remove such specific attributes use `AngularNoNgAttributesSnapshotSerializer` serializer. You need to add `AngularNoNgAttributesSnapshotSerializer` serializer manually (see [`test` app configuration](https://github.com/thymikee/jest-preset-angular/blob/master/e2e/test-app-v9/package.json#L47-L51)).
|
|
91
94
|
|
|
92
95
|
## [AST Transformer](https://github.com/thymikee/jest-preset-angular/blob/master/src/InlineHtmlStripStylesTransformer.ts)
|
|
93
96
|
|
|
@@ -95,11 +98,11 @@ Jest doesn't run in browser nor through dev server. It uses jsdom to abstract br
|
|
|
95
98
|
|
|
96
99
|
## Angular testing environment setup
|
|
97
100
|
|
|
98
|
-
If you look at
|
|
101
|
+
If you look at [`setup-jest.ts`](https://github.com/thymikee/jest-preset-angular/blob/master/src/setup-jest.ts), what we're doing here is we're adding globals required by Angular. With the included [jest-zone-patch](https://github.com/thymikee/jest-preset-angular/tree/master/zone-patch) we also make sure Jest test methods run in Zone context. Then we initialize the Angular testing environment like normal.
|
|
99
102
|
|
|
100
103
|
## Snapshot testing
|
|
101
104
|
|
|
102
|
-
**Since version 1.1.0** it's possible to [snapshot test](http://facebook.github.io/jest/docs/snapshot-testing.html#snapshot-testing-with-jest) your Angular components. Please note it's still under active development and may be a subject of change. You can lookup [
|
|
105
|
+
**Since version 1.1.0** it's possible to [snapshot test](http://facebook.github.io/jest/docs/snapshot-testing.html#snapshot-testing-with-jest) your Angular components. Please note it's still under active development and may be a subject of change. You can lookup [test app](/e2e/test-app-v9/src/app) for details
|
|
103
106
|
|
|
104
107
|
Example:
|
|
105
108
|
|
|
@@ -240,7 +243,7 @@ With Angular 8 and higher, a [change to the way the Angular CLI works](https://g
|
|
|
240
243
|
"emitDecoratorMetadata": true
|
|
241
244
|
```
|
|
242
245
|
|
|
243
|
-
In general, 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 `
|
|
246
|
+
In general, 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 `setup-jest.ts`:
|
|
244
247
|
```typescript
|
|
245
248
|
require('core-js/es/reflect');
|
|
246
249
|
require('core-js/proposals/reflect-metadata');
|
|
@@ -321,12 +324,14 @@ Override `globals` object in Jest config:
|
|
|
321
324
|
"jest": {
|
|
322
325
|
"globals": {
|
|
323
326
|
"ts-jest": {
|
|
324
|
-
"
|
|
327
|
+
"tsconfig": "<rootDir>/tsconfig.custom.json",
|
|
325
328
|
"stringifyContentPathRegex": "\\.html$",
|
|
326
|
-
"astTransformers":
|
|
327
|
-
"
|
|
328
|
-
|
|
329
|
-
|
|
329
|
+
"astTransformers": {
|
|
330
|
+
"before": [
|
|
331
|
+
"jest-preset-angular/build/InlineFilesTransformer",
|
|
332
|
+
"jest-preset-angular/build/StripStylesTransformer"
|
|
333
|
+
]
|
|
334
|
+
}
|
|
330
335
|
}
|
|
331
336
|
}
|
|
332
337
|
}
|
|
@@ -443,7 +448,7 @@ module.exports = function(api) {
|
|
|
443
448
|
|
|
444
449
|
Note: This fix is only relevant to Angular v5 and lower.
|
|
445
450
|
|
|
446
|
-
Since v1.0 this preset doesn't import whole `rxjs` library by default for variety of reasons. This may result in breaking your tests that relied on this behavior. It may however become cumbersome to include e.g. `rxjs/add/operator/map` or `rxjs/add/operator/do` for every test, so as a workaround you can include common operators or other necessary imports in your `
|
|
451
|
+
Since v1.0 this preset doesn't import whole `rxjs` library by default for variety of reasons. This may result in breaking your tests that relied on this behavior. It may however become cumbersome to include e.g. `rxjs/add/operator/map` or `rxjs/add/operator/do` for every test, so as a workaround you can include common operators or other necessary imports in your `setup-jest.ts` file:
|
|
447
452
|
|
|
448
453
|
```js
|
|
449
454
|
import 'jest-preset-angular';
|
|
@@ -460,7 +465,7 @@ import './jestGlobalMocks';
|
|
|
460
465
|
|
|
461
466
|
### Allow vendor libraries like jQuery, etc...
|
|
462
467
|
|
|
463
|
-
The same like normal Jest configuration, you can load jQuery in your Jest setup file. For example your Jest setup file is `
|
|
468
|
+
The same like normal Jest configuration, you can load jQuery in your Jest setup file. For example your Jest setup file is `setup-jest.ts` you can declare jQuery:
|
|
464
469
|
|
|
465
470
|
```js
|
|
466
471
|
window.$ = require('path/to/jquery');
|
|
@@ -479,9 +484,10 @@ Reference: https://github.com/facebook/jest/issues/708
|
|
|
479
484
|
|
|
480
485
|
### Configure other JSDOM versions
|
|
481
486
|
|
|
482
|
-
**Jest**
|
|
487
|
+
**Jest** v26 by default uses **JSDOM** 16 to support Node 10+.
|
|
483
488
|
|
|
484
|
-
If you need a
|
|
489
|
+
If you need a different JSDOM version than the one that ships with Jest, you can install a jsdom environment
|
|
490
|
+
package, e.g. `jest-environment-jsdom-sixteen` and edit your Jest config like so:
|
|
485
491
|
|
|
486
492
|
```
|
|
487
493
|
{
|
|
@@ -17,8 +17,7 @@ var attributesToClean = {
|
|
|
17
17
|
'aria-controls': [/^(?:mat|cdk|ng).*-\d+$/],
|
|
18
18
|
};
|
|
19
19
|
var hasAttributesToRemove = function (attribute) {
|
|
20
|
-
return attributesToRemovePatterns
|
|
21
|
-
.some(function (removePattern) { return attribute.name.startsWith(removePattern); });
|
|
20
|
+
return attributesToRemovePatterns.some(function (removePattern) { return attribute.name.startsWith(removePattern); });
|
|
22
21
|
};
|
|
23
22
|
var hasAttributesToClean = function (attribute) {
|
|
24
23
|
return Object.keys(attributesToClean).some(function (removePatternKey) { return attribute.name === removePatternKey; });
|
|
@@ -29,20 +28,16 @@ var serialize = function (node) {
|
|
|
29
28
|
rest[_i - 1] = arguments[_i];
|
|
30
29
|
}
|
|
31
30
|
var nodeCopy = node.cloneNode(true);
|
|
32
|
-
// Remove angular-specific attributes
|
|
33
31
|
Object.values(nodeCopy.attributes)
|
|
34
32
|
.filter(hasAttributesToRemove)
|
|
35
33
|
.forEach(function (attribute) { return nodeCopy.attributes.removeNamedItem(attribute.name); });
|
|
36
|
-
// Remove angular auto-added classes
|
|
37
34
|
Object.values(nodeCopy.attributes)
|
|
38
35
|
.filter(hasAttributesToClean)
|
|
39
36
|
.forEach(function (attribute) {
|
|
40
37
|
attribute.value = attribute.value
|
|
41
38
|
.split(' ')
|
|
42
39
|
.filter(function (attrValue) {
|
|
43
|
-
return !attributesToClean[attribute.name].some(function (attributeCleanRegex) {
|
|
44
|
-
return attributeCleanRegex.test(attrValue);
|
|
45
|
-
});
|
|
40
|
+
return !attributesToClean[attribute.name].some(function (attributeCleanRegex) { return attributeCleanRegex.test(attrValue); });
|
|
46
41
|
})
|
|
47
42
|
.join(' ');
|
|
48
43
|
if (attribute.value === '') {
|
|
@@ -55,13 +50,11 @@ var serialize = function (node) {
|
|
|
55
50
|
return jestDOMElementSerializer.serialize.apply(jestDOMElementSerializer, __spreadArrays([nodeCopy], rest));
|
|
56
51
|
};
|
|
57
52
|
var serializeTestFn = function (val) {
|
|
58
|
-
return val.attributes !== undefined &&
|
|
59
|
-
.some(function (attribute) { return hasAttributesToRemove(attribute) || hasAttributesToClean(attribute); });
|
|
60
|
-
};
|
|
61
|
-
var test = function (val) {
|
|
62
|
-
return jestDOMElementSerializer.test(val) && serializeTestFn(val);
|
|
53
|
+
return val.attributes !== undefined &&
|
|
54
|
+
Object.values(val.attributes).some(function (attribute) { return hasAttributesToRemove(attribute) || hasAttributesToClean(attribute); });
|
|
63
55
|
};
|
|
56
|
+
var test = function (val) { return jestDOMElementSerializer.test(val) && serializeTestFn(val); };
|
|
64
57
|
module.exports = {
|
|
65
58
|
serialize: serialize,
|
|
66
|
-
test: test
|
|
59
|
+
test: test,
|
|
67
60
|
};
|
|
@@ -6,25 +6,17 @@ var printAttributes = function (val, attributes, print, indent, colors, opts) {
|
|
|
6
6
|
return (opts.spacing +
|
|
7
7
|
indent(colors.prop.open + attribute + colors.prop.close + '=') +
|
|
8
8
|
colors.value.open +
|
|
9
|
-
(val.componentInstance[attribute] &&
|
|
10
|
-
val.componentInstance[attribute].constructor
|
|
11
|
-
? '{[Function ' +
|
|
12
|
-
val.componentInstance[attribute].constructor.name +
|
|
13
|
-
']}'
|
|
9
|
+
(val.componentInstance[attribute] && val.componentInstance[attribute].constructor
|
|
10
|
+
? '{[Function ' + val.componentInstance[attribute].constructor.name + ']}'
|
|
14
11
|
: "\"" + val.componentInstance[attribute] + "\"") +
|
|
15
12
|
colors.value.close);
|
|
16
13
|
})
|
|
17
14
|
.join('');
|
|
18
15
|
};
|
|
19
16
|
var ivyEnabled = function () {
|
|
20
|
-
// Should be required lazily, since it will throw an exception
|
|
21
|
-
// `Cannot resolve parameters...`.
|
|
22
17
|
var ɵivyEnabled = require('@angular/core').ɵivyEnabled;
|
|
23
18
|
return !!ɵivyEnabled;
|
|
24
19
|
};
|
|
25
|
-
// Ivy component definition was stored on the `ngComponentDef`
|
|
26
|
-
// property before `9.0.0-next.10`. Since `9.0.0-next.10` it was
|
|
27
|
-
// renamed to `ɵcmp`.
|
|
28
20
|
var getComponentDef = function (type) { return type.ngComponentDef || type.ɵcmp; };
|
|
29
21
|
var print = function (fixture, print, indent, opts, colors) {
|
|
30
22
|
var nodes = '';
|
|
@@ -33,19 +25,13 @@ var print = function (fixture, print, indent, opts, colors) {
|
|
|
33
25
|
if (ivyEnabled()) {
|
|
34
26
|
var componentDef = getComponentDef(fixture.componentRef.componentType);
|
|
35
27
|
componentName = componentDef.selectors[0][0];
|
|
36
|
-
nodes = Array.from(fixture.componentRef.location.nativeElement.childNodes)
|
|
37
|
-
.map(print)
|
|
38
|
-
.join('');
|
|
28
|
+
nodes = Array.from(fixture.componentRef.location.nativeElement.childNodes).map(print).join('');
|
|
39
29
|
}
|
|
40
30
|
else {
|
|
41
31
|
componentName = fixture.componentRef._elDef.element.name;
|
|
42
32
|
nodes = (fixture.componentRef._view.nodes || [])
|
|
43
33
|
.filter(function (node) { return node && node.hasOwnProperty('renderElement'); })
|
|
44
|
-
.map(function (node) {
|
|
45
|
-
return Array.from(node.renderElement.childNodes)
|
|
46
|
-
.map(print)
|
|
47
|
-
.join('');
|
|
48
|
-
})
|
|
34
|
+
.map(function (node) { return Array.from(node.renderElement.childNodes).map(print).join(''); })
|
|
49
35
|
.join(opts.edgeSpacing);
|
|
50
36
|
}
|
|
51
37
|
var attributes = Object.keys(fixture.componentInstance);
|
|
@@ -70,5 +56,5 @@ var test = function (val) {
|
|
|
70
56
|
};
|
|
71
57
|
module.exports = {
|
|
72
58
|
print: print,
|
|
73
|
-
test: test
|
|
59
|
+
test: test,
|
|
74
60
|
};
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the BSD-style license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree. An additional grant
|
|
6
|
-
* of patent rights can be found in the PATENTS file in the same directory.
|
|
7
|
-
*
|
|
8
|
-
*/
|
|
9
1
|
'use strict';
|
|
10
2
|
var HTML_ELEMENT_REGEXP = /Comment/;
|
|
11
3
|
var test = function (value) {
|
|
@@ -18,5 +10,5 @@ var test = function (value) {
|
|
|
18
10
|
var print = function () { return ''; };
|
|
19
11
|
module.exports = {
|
|
20
12
|
print: print,
|
|
21
|
-
test: test
|
|
13
|
+
test: test,
|
|
22
14
|
};
|
|
@@ -1,118 +1,56 @@
|
|
|
1
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
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.factory = exports.version = exports.name = void 0;
|
|
8
4
|
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
|
|
12
|
-
/** Angular component decorator TemplateUrl property name */
|
|
13
5
|
var TEMPLATE_URL = 'templateUrl';
|
|
14
|
-
/** Angular component decorator StyleUrls property name */
|
|
15
6
|
var STYLE_URLS = 'styleUrls';
|
|
16
|
-
/** Angular component decorator Template property name */
|
|
17
7
|
var TEMPLATE = 'template';
|
|
18
|
-
/** Node require function name */
|
|
19
8
|
var REQUIRE = 'require';
|
|
20
|
-
/**
|
|
21
|
-
* Property names anywhere in an angular project to transform
|
|
22
|
-
*/
|
|
23
9
|
var TRANSFORM_PROPS = [TEMPLATE_URL, STYLE_URLS];
|
|
24
|
-
/**
|
|
25
|
-
* Transformer ID
|
|
26
|
-
* @internal
|
|
27
|
-
*/
|
|
28
10
|
exports.name = 'angular-component-inline-files';
|
|
29
|
-
// increment this each time the code is modified
|
|
30
|
-
/**
|
|
31
|
-
* Transformer Version
|
|
32
|
-
* @internal
|
|
33
|
-
*/
|
|
34
11
|
exports.version = 1;
|
|
35
|
-
/**
|
|
36
|
-
* The factory of hoisting transformer factory
|
|
37
|
-
* @internal
|
|
38
|
-
*/
|
|
39
12
|
function factory(cs) {
|
|
40
|
-
/**
|
|
41
|
-
* Our compiler (typescript, or a module with typescript-like interface)
|
|
42
|
-
*/
|
|
43
13
|
var ts = cs.compilerModule;
|
|
44
14
|
var createStringLiteral = TransformUtils_1.getCreateStringLiteral(ts);
|
|
45
|
-
/**
|
|
46
|
-
* Traverses the AST down to the relevant assignments anywhere in the file
|
|
47
|
-
* and returns a boolean indicating if it should be transformed.
|
|
48
|
-
*/
|
|
49
15
|
function isPropertyAssignmentToTransform(node) {
|
|
50
|
-
return
|
|
51
|
-
ts.isIdentifier(node.name) &&
|
|
52
|
-
TRANSFORM_PROPS.includes(node.name.text));
|
|
16
|
+
return ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && TRANSFORM_PROPS.includes(node.name.text);
|
|
53
17
|
}
|
|
54
|
-
/**
|
|
55
|
-
* Clones the assignment and manipulates it depending on its name.
|
|
56
|
-
* @param node the property assignment to change
|
|
57
|
-
*/
|
|
58
18
|
function transfromPropertyAssignmentForJest(node) {
|
|
59
19
|
var mutableAssignment = ts.getMutableClone(node);
|
|
60
20
|
var assignmentNameText = mutableAssignment.name.text;
|
|
61
21
|
switch (assignmentNameText) {
|
|
62
22
|
case TEMPLATE_URL:
|
|
63
|
-
// replace 'templateUrl' with 'template'
|
|
64
|
-
// reuse the right-hand-side literal (the filepath) from the assignment
|
|
65
23
|
var pathLiteral = mutableAssignment.initializer;
|
|
66
|
-
// fix templatePathLiteral if it was a non-relative path
|
|
67
24
|
if (ts.isStringLiteral(pathLiteral)) {
|
|
68
|
-
|
|
69
|
-
if (pathLiteral.text &&
|
|
70
|
-
!pathLiteral.text.match(/^(\.\/|\.\.\/|\/)/)) {
|
|
71
|
-
// make path relative by prepending './'
|
|
25
|
+
if (pathLiteral.text && !pathLiteral.text.match(/^(\.\/|\.\.\/|\/)/)) {
|
|
72
26
|
pathLiteral = createStringLiteral("./" + pathLiteral.text);
|
|
73
27
|
}
|
|
74
28
|
}
|
|
75
|
-
|
|
76
|
-
var requireCall = ts.createCall(
|
|
77
|
-
/* expression */ ts.createIdentifier(REQUIRE),
|
|
78
|
-
/* type arguments */ undefined,
|
|
79
|
-
/* arguments array */ [pathLiteral]);
|
|
29
|
+
var requireCall = ts.createCall(ts.createIdentifier(REQUIRE), undefined, [pathLiteral]);
|
|
80
30
|
mutableAssignment.name = ts.createIdentifier(TEMPLATE);
|
|
81
31
|
mutableAssignment.initializer = requireCall;
|
|
82
32
|
break;
|
|
83
33
|
case STYLE_URLS:
|
|
84
|
-
// replace styleUrls value with emtpy array
|
|
85
|
-
// inlining all urls would be way more complicated and slower
|
|
86
34
|
mutableAssignment.initializer = ts.createArrayLiteral();
|
|
87
35
|
break;
|
|
36
|
+
default:
|
|
37
|
+
break;
|
|
88
38
|
}
|
|
89
39
|
return mutableAssignment;
|
|
90
40
|
}
|
|
91
|
-
/**
|
|
92
|
-
* Create a source file visitor which will visit all nodes in a source file
|
|
93
|
-
* @param ctx The typescript transformation context
|
|
94
|
-
* @param _ The owning source file
|
|
95
|
-
*/
|
|
96
41
|
function createVisitor(ctx, _) {
|
|
97
|
-
/**
|
|
98
|
-
* Our main visitor, which will be called recursively for each node in the source file's AST
|
|
99
|
-
* @param node The node to be visited
|
|
100
|
-
*/
|
|
101
42
|
var visitor = function (node) {
|
|
102
43
|
var resultNode = node;
|
|
103
|
-
// before we create a deep clone to modify, we make sure that
|
|
104
|
-
// this is an assignment which we want to transform
|
|
105
44
|
if (isPropertyAssignmentToTransform(node)) {
|
|
106
|
-
// get transformed node with changed properties
|
|
107
45
|
resultNode = transfromPropertyAssignmentForJest(node);
|
|
108
46
|
}
|
|
109
|
-
// look for interesting assignments inside this node in any case
|
|
110
47
|
resultNode = ts.visitEachChild(resultNode, visitor, ctx);
|
|
111
|
-
// finally return the currently visited node
|
|
112
48
|
return resultNode;
|
|
113
49
|
};
|
|
114
50
|
return visitor;
|
|
115
51
|
}
|
|
116
|
-
return function (ctx) { return function (sf) {
|
|
52
|
+
return function (ctx) { return function (sf) {
|
|
53
|
+
return ts.visitNode(sf, createVisitor(ctx, sf));
|
|
54
|
+
}; };
|
|
117
55
|
}
|
|
118
56
|
exports.factory = factory;
|