Skip to content

Commit

Permalink
feat: component serializer without ng-* attributes (#97)
Browse files Browse the repository at this point in the history
* feat: component serializer without Angular specific attributes like _nghost
  and ng-reflect-*
* fix(ci): disable cache in example app to ensure preset currency
  • Loading branch information
sharikovvladislav authored and wtho committed Apr 28, 2019
1 parent 61c391a commit 1079528
Show file tree
Hide file tree
Showing 33 changed files with 316 additions and 35 deletions.
18 changes: 10 additions & 8 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,21 @@ jobs:
steps:
- attach_workspace:
at: .
- restore_cache:
keys:
- yarn-cache-example-{{ .Branch }}-{{ checksum "yarn.lock" }}
- yarn-cache-example-{{ .Branch }}-
# disabling cache here as it created issues with the preset in the root
# not being used, as older version in cache was available
#- restore_cache:
# keys:
# - yarn-cache-example-{{ .Branch }}-{{ checksum "yarn.lock" }}
# - yarn-cache-example-{{ .Branch }}-
- run:
name: Install Example Dependencies
command: |
cd example
yarn install --frozen-lockfile
- save_cache:
key: yarn-cache-example-{{ .Branch }}-{{ checksum "yarn.lock" }}
paths:
- ./example/node_modules
#- save_cache:
# key: yarn-cache-example-{{ .Branch }}-{{ checksum "yarn.lock" }}
# paths:
# - ./example/node_modules
- run:
name: Test Example
command: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
InlineHtmlStripStylesTransformer.js
*.log
.idea
30 changes: 30 additions & 0 deletions AngularNoNgAttributesSnapshotSerializer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict';

const jestDOMElementSerializer = require('pretty-format').plugins.DOMElement;

const attributesToRemovePatterns = ['ng-reflect', '_nghost', '_ngcontent', 'ng-version'];

const hasAttributesToRemove = (attribute) =>
attributesToRemovePatterns
.some(removePattern => attribute.name.startsWith(removePattern));

const serialize = (node, ...rest) => {
const nodeCopy = node.cloneNode(true);
Object.values(nodeCopy.attributes)
.filter(hasAttributesToRemove)
.forEach(attribute => nodeCopy.attributes.removeNamedItem(attribute.name));

return jestDOMElementSerializer.serialize(nodeCopy, ...rest);
};

const serializeTestFn = (val) => {
return val.attributes !== undefined && Object.values(val.attributes)
.some(hasAttributesToRemove)
};
const test = val =>
jestDOMElementSerializer.test(val) && serializeTestFn(val);

module.exports = {
serialize: serialize,
test: test
};
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## Changelog (master)

* Added `AngularNoNgAttributesSnapshotSerializer`. Using this serializer makes snapshots clearer and more human-readable. You have to apply this serializer manually by redefining `snapshotSerializers` `jest` option.
* Fixed a CI cache issue in the example app, which would not always use the current version of the preset in the test runs.

### v7.0.0

#### Features
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ module.exports = {
- `"moduleFileExtensions"` – our modules are TypeScript and JavaScript files
- `"moduleNameMapper"` – if you're using absolute imports here's how to tell Jest where to look for them; uses regex
- `"setupFilesAfterEnv"` – this is the heart of our config, in this file we'll setup and patch environment within tests are running
- `"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.
- `"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.
- `"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 [`example` app configuration](https://github.com/thymikee/jest-preset-angular/blob/master/example/package.json#L47-L51)).

## [AST Transformer](https://github.com/thymikee/jest-preset-angular/blob/master/src/InlineHtmlStripStylesTransformer.ts)

Expand Down
5 changes: 5 additions & 0 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@
},
"jest": {
"preset": "jest-preset-angular",
"snapshotSerializers": [
"jest-preset-angular/AngularNoNgAttributesSnapshotSerializer.js",
"jest-preset-angular/AngularSnapshotSerializer.js",
"jest-preset-angular/HTMLCommentSerializer.js"
],
"moduleNameMapper": {
"\\.(jpg|jpeg|png)$": "<rootDir>/__mocks__/image.js",
"^@lib/(.*)$": "<rootDir>/src/lib/$1"
Expand Down
Empty file removed example/src/app/app.component.css
Empty file.
9 changes: 3 additions & 6 deletions example/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
import {Component, HostBinding, OnInit} from '@angular/core';
import {Component, HostBinding} from '@angular/core';
import {trigger, transition, style, animate} from '@angular/animations';

@Component({
selector: 'app-root',
animations: [slideToLeft()],
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit{
export class AppComponent {
@HostBinding('@routerTransition')
title = 'app works!';
hasClass = true;
variableWithPrecedingDolar = 1234;

ngOnInit() {}
}

export function slideToLeft() {
Expand Down
6 changes: 5 additions & 1 deletion example/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@ import { CalcComponent } from './calc/calc.component';
import { SimpleComponent } from './simple/simple.component';
import { OnPushComponent } from './on-push/on-push.component';
import { HeroesComponent } from './heroes/heroes.component';
import { SimpleWithStylesComponent } from './simple-with-styles/simple-with-styles.component';
import { ChildComponent } from './medium/child.component';

@NgModule({
declarations: [
AppComponent,
CalcComponent,
SimpleComponent,
OnPushComponent,
HeroesComponent
HeroesComponent,
SimpleWithStylesComponent,
ChildComponent
],
imports: [
BrowserModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ exports[`CalcComponent should snap 1`] = `
>
<p
class="a-default-class"
ng-reflect-klass="a-default-class"
ng-reflect-ng-class="[object Object]"
>
calc works! 1337 another text node test-image-stub
</p>
Expand Down
Empty file.
3 changes: 1 addition & 2 deletions example/src/app/calc/calc.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ const image = require('assets/its_something.png');
another text node
{{image}}
</p>
`,
styleUrls: ['./calc.component.css']
`
})
export class CalcComponent implements OnInit {
@Input() hasAClass = false;
Expand Down
1 change: 0 additions & 1 deletion example/src/app/heroes/heroes.component.css

This file was deleted.

3 changes: 1 addition & 2 deletions example/src/app/heroes/heroes.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { HeroService } from '../service/hero.service';

@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
templateUrl: './heroes.component.html'
})
export class HeroesComponent implements OnInit {
heroes: Hero[];
Expand Down
36 changes: 36 additions & 0 deletions example/src/app/medium/__snapshots__/medium.component.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`MediumComponent snapshot test 1`] = `
<app-medium
anotherVar="false"
someVar={[Function Boolean]}
>
<div
class="some-wrapper-class"
>
diary works!
<div
class="inner-class"
>
<div>
another case
</div>
<span>
some html
</span>
</div>
<div>
one more case case
</div>
<div>
<app-child-component
someinput="someVar"
>
stubbedBody
</app-child-component>
</div>
</div>
</app-medium>
`;
20 changes: 20 additions & 0 deletions example/src/app/medium/child.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Component, Input } from '@angular/core';

@Component({
selector: 'app-child-component',
template: `
<div class="child">
{{ someInput }}
<div>
rly
<p>complex</p>
<div>component
<div>oh my god!</div>
</div>
</div>
</div>
`
})
export class ChildComponent {
@Input() someInput = null;
}
34 changes: 34 additions & 0 deletions example/src/app/medium/medium.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { MediumComponent } from './medium.component';
import { ChildComponent } from './child.component';

describe('MediumComponent', () => {
let component: MediumComponent;
let fixture: ComponentFixture<MediumComponent>;

beforeEach(
async(() => {
TestBed.configureTestingModule({
declarations: [MediumComponent, ChildComponent],
})
.overrideComponent(ChildComponent, {set: {template: 'stubbedBody'}})
.compileComponents();
}),
);

beforeEach(() => {
fixture = TestBed.createComponent(MediumComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});

it('snapshot test', () => {
expect(fixture).toMatchSnapshot();
});
});
21 changes: 21 additions & 0 deletions example/src/app/medium/medium.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Component } from '@angular/core';

@Component({
selector: 'app-medium',
template: `
<div class="some-wrapper-class">
diary works!
<div *ngIf="someVar" class="inner-class">
<div *ngIf="anotherVar" class="inner-hidden"></div>
<div>another case</div>
<span>some html</span>
</div>
<div>one more case case</div>
<div><app-child-component someInput="someVar"></app-child-component></div>
</div>
`
})
export class MediumComponent {
someVar = true;
anotherVar = false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`NgReflectAsTextComponent snapshots 1`] = `
<app-ng-reflect-as-text>
<p
data-some-attr="ng-reflect-as-attr-arg works"
>
ng-reflect-as-text works!
</p>
</app-ng-reflect-as-text>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<p data-some-attr="ng-reflect-as-attr-arg works">
ng-reflect-as-text works!
</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { NgReflectAsTextComponent } from './ng-reflect-as-text.component';

describe('NgReflectAsTextComponent', () => {
let component: NgReflectAsTextComponent;
let fixture: ComponentFixture<NgReflectAsTextComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ NgReflectAsTextComponent ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(NgReflectAsTextComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('snapshots', () => {
expect(fixture).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Component } from '@angular/core';

@Component({
selector: 'app-ng-reflect-as-text',
templateUrl: './ng-reflect-as-text.component.html'
})
export class NgReflectAsTextComponent {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`SimpleWithStylesComponent should generate snapshot without nghost/ngcontent 1`] = `
<app-simple-with-styles>
<p>
simple-with-styles works!
</p><div
class="some-class"
>
<app-child-component>
<div
class="child"
>
<div>
rly
<p>
complex
</p>
<div>
component
<div>
oh my god!
</div>
</div>
</div>
</div>
</app-child-component>
</div>
</app-simple-with-styles>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<p>
simple-with-styles works!
</p>
<div class="some-class">
<app-child-component></app-child-component>
</div>
Loading

0 comments on commit 1079528

Please sign in to comment.