Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: add more troubleshooting docs #129

Merged
merged 7 commits into from
Mar 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 122 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,126 @@ exports[`CalcComponent should snap 1`] = `
`;
```

### Removing empty lines and white-spaces in component snaphots

You will immediately notice, that your snapshot files contain a lot of white spaces and blank lines. This is not an issue with Jest, rather with Angular. It can be mitigated via Angular compiler by setting `preserveWhitespaces: false`

> By default it's set to `true` Angular 5.x, although it may change to be set to `false` in upcoming versions
> (if that occurs, you can stop reading right here, because your issue has been already solved)

Your `TestBed` setup should look like following:

```ts
describe('Component snapshot tests', ()=>{
// you need to turn TS checking because it's an private API
const compilerConfig = {preserveWhitespaces: false} as any

beforeEach(() => {
TestBed.configureCompiler(compilerConfig)
.configureTestingModule({...});
});

})
```

This is indeed very repetitive, so you can extract this in a helper function:

```ts
// test-config.helper.ts

import { TestBed } from '@angular/core/testing'

type CompilerOptions = Partial<{
providers: any[]
useJit: boolean
preserveWhitespaces: boolean
}>
export type ConfigureFn = (testBed: typeof TestBed) => void

export const configureTests = (configure: ConfigureFn, compilerOptions: CompilerOptions = {}) => {
const compilerConfig: CompilerOptions = {
preserveWhitespaces: false,
...compilerOptions,
}

const configuredTestBed = TestBed.configureCompiler(compilerConfig)

configure(configuredTestBed)

return configuredTestBed.compileComponents().then(() => configuredTestBed)
}
```

And setup your test with that function like following:

```ts
// foo.component.spec.ts

import { async, ComponentFixture } from '@angular/core/testing'

import { configureTests, ConfigureFn } from '../test-config.helper'

import { AppComponent } from './foo.component';

describe('Component snapshots', () => {

let fixture: ComponentFixture<FooComponent>;
let component: FooComponent;

beforeEach(
async(() => {
const configure: ConfigureFn = testBed => {
testBed.configureTestingModule({
declarations: [FooComponent],
imports: [...],
schemas: [NO_ERRORS_SCHEMA],
});
};

configureTests(configure).then(testBed => {
fixture = testBed.createComponent(FooComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
})
);

it(`should create snapshots without blank lines/white spaces`, () => {
expect(fixture).toMatchSnapshot();
});

})
```

## Troubleshooting

Problems may arise if you're using custom builds (this preset is tailored for `angular-cli` as firsty priority). Please be adivsed that every entry in default configuration may be overriden to best suite your app's needs.

### @Input() bindings are not reflected into fixture when `ChangeDetectionStrategy.OnPush` is used

This issue is not related to Jest, [it's a known Angular bug](https://github.com/angular/angular/issues/12313)

To mitigate this, you need to wrap your component under test, into some container component with default change detection strategy (`ChangeDetectionStrategy.Default`) and pass props through it, or overwrite change detection strategy within `TestBed` setup, if it's not critical for the test.

```ts
// override change detection strategy
beforeEach(
async(() => {
TestBed.configureTestingModule({ declarations: [PizzaItemComponent] })
.overrideComponent(PizzaItemComponent, {
set: { changeDetection: ChangeDetectionStrategy.Default },
})
.compileComponents();
})
);
```

### The animation trigger "transformMenu" has failed
JSDOM missing transform property when using Angular Material, there is a workaround for it.

Add this to your `jestGlobalMocks` file
```

```js
Object.defineProperty(document.body.style, 'transform', {
value: () => {
return {
Expand All @@ -148,7 +259,8 @@ import MyComponent from 'app/my.component';
import MyStuff from 'src/testing/my.stuff';
```
However, if your directory structure differ from that provided by `angular-cli` you can adjust `moduleNameMapper` in Jest config:
```js

```json
{
"jest": {
"moduleNameMapper": {
Expand All @@ -169,7 +281,7 @@ Override `globals` object in Jest config:
"globals": {
"ts-jest": {
"tsConfigFile": "src/tsconfig.custom.json"
},
},
"__TRANSFORM_HTML__": true
}
}
Expand All @@ -183,7 +295,8 @@ If you choose to overide `globals` in order to point at a specific tsconfig, you
This means, that a file is not transformed through TypeScript compiler, e.g. because it is a JS file with TS syntax, or it is published to npm as uncompiled source files. Here's what you can do.

#### Adjust your `transformIgnorePatterns` whitelist:
```js

```json
{
"jest": {
"transformIgnorePatterns": [
Expand All @@ -205,7 +318,7 @@ By default Jest doesn't transform `node_modules`, because they should be valid J
This tells `ts-jest` (a preprocessor this preset using to transform TS files) to treat JS files the same as TS ones.

#### Transpile js files through `babel-jest`
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.
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.
1. Install `babel-preset-env` and add `.babelrc` (or modify existing if needed) with that contents:
```
{
Expand Down Expand Up @@ -245,17 +358,17 @@ import './jestGlobalMocks';

The same like normal Jest configuration, you can load jQuery in your Jest setup file. For example your Jest setup file is `setupJest.ts` you can declare jQuery:

```
```js
window.$ = require('path/to/jquery');
```

or
or

```
```js
import $ from 'jquery';
global.$ = global.jQuery = $;
```

The same declaration can be applied to other vendor libraries.

Reference: https://github.com/facebook/jest/issues/708
41 changes: 17 additions & 24 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,44 +15,37 @@
},
"private": true,
"dependencies": {
"@angular/animations": "^5.2.2",
"@angular/common": "^5.2.2",
"@angular/compiler": "^5.2.2",
"@angular/core": "^5.2.2",
"@angular/forms": "^5.2.2",
"@angular/http": "^5.2.2",
"@angular/platform-browser": "^5.2.2",
"@angular/platform-browser-dynamic": "^5.2.2",
"@angular/router": "^5.2.2",
"@angular/animations": "^5.2.8",
"@angular/common": "^5.2.8",
"@angular/compiler": "^5.2.8",
"@angular/core": "^5.2.8",
"@angular/forms": "^5.2.8",
"@angular/http": "^5.2.8",
"@angular/platform-browser": "^5.2.8",
"@angular/platform-browser-dynamic": "^5.2.8",
"@angular/router": "^5.2.8",
"core-js": "^2.5.3",
"rxjs": "^5.5.6",
"zone.js": "^0.8.20"
},
"devDependencies": {
"@angular/cli": "^1.6.6",
"@angular/compiler-cli": "^5.2.2",
"@angular/cli": "^1.7.3",
"@angular/compiler-cli": "^5.2.8",
"@types/node": "~6.0.60",
"codelyzer": "^4.1.0",
"jasmine-core": "~2.6.2",
"jasmine-spec-reporter": "~4.1.0",
"jest": "^22.1.4",
"jest-preset-angular": "^5.0.0",
"karma": "~1.7.0",
"karma-chrome-launcher": "~2.1.1",
"karma-cli": "~1.0.1",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"codelyzer": "^4.2.1",
"jest": "^22.4.2",
"jest-preset-angular": "^5.2.1",
"protractor": "~5.1.2",
"ts-node": "~4.1.0",
"tslint": "~5.9.1",
"typescript": "~2.5.3"
"typescript": "2.6.2"
},
"jest": {
"preset": "jest-preset-angular",
"setupTestFrameworkScriptFile": "<rootDir>/src/setupJest.ts",
"moduleNameMapper": {
"\\.(jpg|jpeg|png)$": "<rootDir>/__mocks__/image.js"
"\\.(jpg|jpeg|png)$": "<rootDir>/__mocks__/image.js",
"@lib/(.*)": "<rootDir>/src/lib/$1"
}
}
}
12 changes: 2 additions & 10 deletions example/src/app/__snapshots__/app.component.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,24 @@ exports[`AppComponent snaps 1`] = `
<h1
class="ng-tns-c1-0"
>

app works!

app works!
<app-calc
class="ng-tns-c1-0"
/>


<span
class="ng-tns-c1-0"
>
aaa $1234
</span>



<span
class="ng-tns-c1-0 ng-star-inserted"
style=""
>
ddd
</span>

\`test'chars""
\`test'chars""

</h1>

</app-root>
`;
41 changes: 24 additions & 17 deletions example/src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
import {TestBed, async, fakeAsync, tick} from '@angular/core/testing';
import {NO_ERRORS_SCHEMA} from '@angular/core';
import {AppComponent} from './app.component';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { async, fakeAsync, tick, ComponentFixture } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';

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

import { AppComponent } from './app.component';

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

beforeEach(
async(() => {
TestBed.configureTestingModule({
declarations: [AppComponent],
imports: [NoopAnimationsModule],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
const configure: ConfigureFn = testBed => {
testBed.configureTestingModule({
declarations: [AppComponent],
imports: [NoopAnimationsModule],
schemas: [NO_ERRORS_SCHEMA],
});
};

configureTests(configure).then(testBed => {
fixture = testBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
})
);

beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
});

it(
'should create the app',
async(() => {
const app = fixture.debugElement.componentInstance;
const app = component;
expect(app).toBeTruthy();
})
);
Expand All @@ -36,7 +43,7 @@ describe('AppComponent', () => {
it(
`should have as title 'app works!'`,
async(() => {
const app = fixture.debugElement.componentInstance;
const app = component;
expect(app.title).toEqual('app works!');
})
);
Expand Down
4 changes: 3 additions & 1 deletion example/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { AppComponent } from './app.component';
import { CalcComponent } from './calc/calc.component';
import { SimpleComponent } from './simple/simple.component';
import { OnPushComponent } from './on-push/on-push.component';

@NgModule({
declarations: [
AppComponent,
CalcComponent,
SimpleComponent
SimpleComponent,
OnPushComponent
],
imports: [
BrowserModule,
Expand Down
11 changes: 2 additions & 9 deletions example/src/app/calc/__snapshots__/calc.component.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,12 @@ exports[`CalcComponent should snap 1`] = `
image={[Function String]}
prop1={[Function Number]}
>

<p
<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

calc works! 1337 another text node test-image-stub
</p>

</app-calc>
`;
Loading