Skip to content

Commit

Permalink
feat: transform 'styles' only in decorator
Browse files Browse the repository at this point in the history
Until now 'templateUrl', 'styleUrls' and 'styles' were transformed
everywhere, where they were assigned.

The new implementation of the AstTransformers splits it in two:
* InlineFilesTransformer, which inlines `templateUrl` and removes
  `styleUrls` file references
* StripStylesTransformer, which removes the `styles` property, but only
  if it is assigned inside the `@component` decorator

Tests were added to ensure the transformers behave as desired in edge
cases regarding `styleUrls` and `styles`.
  • Loading branch information
wtho committed Jun 30, 2019
1 parent 4f1504d commit 351e919
Show file tree
Hide file tree
Showing 10 changed files with 457 additions and 130 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
node_modules
InlineHtmlStripStylesTransformer.js
InlineFilesTransformer.js
StripStylesTransformer.js
TransformUtils.js
*.log
.idea
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
## Changelog (master)

* (**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)).

#### Migration Guide
* If the `astTransformers` are referenced in a custom `jest` config, `[ 'jest-preset-angular/InlineFilesTransformer', 'jest-preset-angular/StripStylesTransformer']` have to be set instead.

### v7.1.0

#### Features
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/*
* Code is inspired by
* https://github.com/kulshekhar/ts-jest/blob/25e1c63dd3797793b0f46fa52fdee580b46f66ae/src/transformers/hoist-jest.spec.ts
*
*
*/

import * as tsc from 'typescript'
import * as transformer from '../InlineHtmlStripStylesTransformer'
import * as tsc from 'typescript';
import * as transformer from '../InlineFilesTransformer';

const CODE_WITH_TEMPLATE_URL = `
import { Component } from '@angular/core';
Expand All @@ -15,7 +15,7 @@ const CODE_WITH_TEMPLATE_URL = `
})
export class AngularComponent {
}
`
`;

const CODE_WITH_NON_RELATIVE_TEMPLATE_URL = `
import { Component } from '@angular/core';
Expand All @@ -25,7 +25,7 @@ const CODE_WITH_NON_RELATIVE_TEMPLATE_URL = `
})
export class AngularComponent {
}
`
`;

const CODE_WITH_STYLE_URLS = `
import { Component } from '@angular/core';
Expand All @@ -38,20 +38,20 @@ const CODE_WITH_STYLE_URLS = `
})
export class AngularComponent {
}
`
`;

const CODE_WITH_STYLES = `
import { Component } from '@angular/core';
@Component({
styles: [
'body: { display: none }',
'html: { background-color: red }'
'body { display: none }',
'html { background-color: red }'
]
})
export class AngularComponent {
}
`
`;

const CODE_WITH_ALL_DECORATOR_PROPERTIES = `
import { Component } from '@angular/core';
Expand All @@ -66,8 +66,8 @@ const CODE_WITH_ALL_DECORATOR_PROPERTIES = `
'./basic-styles.scss'
],
styles: [
'body: { display: none }',
'html: { background-color: red }'
'body { display: none }',
'html { background-color: red }'
],
unaffectedProperty: 'whatever'
})
Expand All @@ -76,7 +76,7 @@ const CODE_WITH_ALL_DECORATOR_PROPERTIES = `
})
export class AngularComponent {
}
`
`;

const CODE_WITH_CUSTOM_DECORATOR = `
import { Component as CustomDecoratorName } from '@angular/core';
Expand All @@ -86,7 +86,7 @@ const CODE_WITH_CUSTOM_DECORATOR = `
})
export class AngularComponent {
}
`
`;

const CODE_TEST_WITH_TEMPLATE_URL_OVERRIDE = `
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
Expand Down Expand Up @@ -117,62 +117,73 @@ describe('AComponent', () => {
expect(fixture).toMatchSnapshot();
});
});
`


`;

const CODE_WITH_ASSIGNMENTS_OUTSIDE_DECORATOR = `
const assignmentsToNotBeTransformed = {
styles: [{
color: 'red'
}]
};
const assignmentsToBeTransformed = {
styleUrls: ['./some-styles.css'],
templateUrl: './some-styles.css'
};
`;

const createFactory = () => {
return transformer.factory({ compilerModule: tsc } as any)
}
const transpile = (source: string) => tsc.transpileModule(source, { transformers: { before: [createFactory()] } })

describe('inlining template and stripping styles', () => {
it('should have correct signature', () => {
expect(transformer.name).toBe('angular-component-inline-template-strip-styles')
expect(typeof transformer.version).toBe('number')
expect(transformer.version).toBeGreaterThan(0)
expect(typeof transformer.factory).toBe('function')
})
return transformer.factory({ compilerModule: tsc } as any);
};
const transpile = (source: string) =>
tsc.transpileModule(source, { transformers: { before: [createFactory()] } });

it('should strip styleUrl assignment', () => {
const out = transpile(CODE_WITH_STYLE_URLS)

expect(out.outputText).toMatchSnapshot()
})

it('should strip styles assignment', () => {
const out = transpile(CODE_WITH_STYLES)
describe('inlining template and stripping styleUrls', () => {
it('should strip styleUrls assignment', () => {
const out = transpile(CODE_WITH_STYLE_URLS);

expect(out.outputText).toMatchSnapshot()
})
expect(out.outputText).toMatchSnapshot();
});

it('should inline templateUrl assignment', () => {
const out = transpile(CODE_WITH_TEMPLATE_URL)
const out = transpile(CODE_WITH_TEMPLATE_URL);

expect(out.outputText).toMatchSnapshot()
})
expect(out.outputText).toMatchSnapshot();
});

it('should not strip styles assignment', () => {
const out = transpile(CODE_WITH_STYLES);

expect(out.outputText).toMatchSnapshot();
});

it('should inline non-relative templateUrl assignment and make it relative', () => {
const out = transpile(CODE_WITH_NON_RELATIVE_TEMPLATE_URL)
const out = transpile(CODE_WITH_NON_RELATIVE_TEMPLATE_URL);

expect(out.outputText).toMatchSnapshot()
})
expect(out.outputText).toMatchSnapshot();
});

it('should handle all transformable decorator assignments', () => {
const out = transpile(CODE_WITH_ALL_DECORATOR_PROPERTIES)
const out = transpile(CODE_WITH_ALL_DECORATOR_PROPERTIES);

expect(out.outputText).toMatchSnapshot()
})
expect(out.outputText).toMatchSnapshot();
});

it('should handle all decorator assignments in differently named decorators', () => {
const out = transpile(CODE_WITH_CUSTOM_DECORATOR)
const out = transpile(CODE_WITH_CUSTOM_DECORATOR);

expect(out.outputText).toMatchSnapshot()
})
expect(out.outputText).toMatchSnapshot();
});

it('should handle templateUrl in test file outside decorator', () => {
const out = transpile(CODE_TEST_WITH_TEMPLATE_URL_OVERRIDE)
const out = transpile(CODE_TEST_WITH_TEMPLATE_URL_OVERRIDE);

expect(out.outputText).toMatchSnapshot()
})
})
expect(out.outputText).toMatchSnapshot();
});

it('should not transform styles outside decorator', () => {
const out = transpile(CODE_WITH_ASSIGNMENTS_OUTSIDE_DECORATOR);

expect(out.outputText).toMatchSnapshot();
});
});
61 changes: 61 additions & 0 deletions __tests__/StripStylesTransformer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Code is inspired by
* https://github.com/kulshekhar/ts-jest/blob/25e1c63dd3797793b0f46fa52fdee580b46f66ae/src/transformers/hoist-jest.spec.ts
*
*/

import * as tsc from 'typescript';
import * as transformer from '../StripStylesTransformer';

const CODE_WITH_STYLES_AND_OTHER_ASSIGNMENTS = `
import { Component } from '@angular/core';
@SomeDecorator({
value: 'test',
styles: [
':host { background-color: red }'
],
})
@Component({
templateUrl: './page.html',
styleUrls: [
'./fancy-styles.css',
'./basic-styles.scss'
],
styles: [
'body { display: none }',
'html { background-color: red }'
],
unaffectedProperty: 'whatever'
})
export class AngularComponent {
}
`;

const CODE_WITH_ASSIGNMENT_OUTSIDE_DECORATOR = `
const assignmentsToNotBeTransformed = {
styles: [{
color: 'red'
}]
};
`;

const createFactory = () => {
return transformer.factory({ compilerModule: tsc } as any);
};
const transpile = (source: string) =>
tsc.transpileModule(source, { transformers: { before: [createFactory()] } });

describe('inlining template and stripping styles', () => {
it('should not strip styleUrls assignment', () => {
const out = transpile(CODE_WITH_STYLES_AND_OTHER_ASSIGNMENTS);

expect(out.outputText).toMatchSnapshot();
});

it('should not transform styles outside decorator', () => {
const out = transpile(CODE_WITH_ASSIGNMENT_OUTSIDE_DECORATOR);

expect(out.outputText).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`inlining template and stripping styles should handle all decorator assignments in differently named decorators 1`] = `
exports[`inlining template and stripping styleUrls should handle all decorator assignments in differently named decorators 1`] = `
"\\"use strict\\";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
Expand All @@ -24,7 +24,7 @@ exports.AngularComponent = AngularComponent;
"
`;

exports[`inlining template and stripping styles should handle all transformable decorator assignments 1`] = `
exports[`inlining template and stripping styleUrls should handle all transformable decorator assignments 1`] = `
"\\"use strict\\";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
Expand All @@ -44,7 +44,10 @@ var AngularComponent = /** @class */ (function () {
core_1.Component({
template: require('./page.html'),
styleUrls: [],
styles: [],
styles: [
'body { display: none }',
'html { background-color: red }'
],
unaffectedProperty: 'whatever'
}),
SomeOtherDecorator({
Expand All @@ -57,7 +60,7 @@ exports.AngularComponent = AngularComponent;
"
`;

exports[`inlining template and stripping styles should handle templateUrl in test file outside decorator 1`] = `
exports[`inlining template and stripping styleUrls should handle templateUrl in test file outside decorator 1`] = `
"\\"use strict\\";
Object.defineProperty(exports, \\"__esModule\\", { value: true });
var testing_1 = require(\\"@angular/core/testing\\");
Expand Down Expand Up @@ -85,7 +88,7 @@ describe('AComponent', function () {
"
`;

exports[`inlining template and stripping styles should inline non-relative templateUrl assignment and make it relative 1`] = `
exports[`inlining template and stripping styleUrls should inline non-relative templateUrl assignment and make it relative 1`] = `
"\\"use strict\\";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
Expand All @@ -109,7 +112,7 @@ exports.AngularComponent = AngularComponent;
"
`;

exports[`inlining template and stripping styles should inline templateUrl assignment 1`] = `
exports[`inlining template and stripping styleUrls should inline templateUrl assignment 1`] = `
"\\"use strict\\";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
Expand All @@ -133,7 +136,7 @@ exports.AngularComponent = AngularComponent;
"
`;

exports[`inlining template and stripping styles should strip styleUrl assignment 1`] = `
exports[`inlining template and stripping styleUrls should not strip styles assignment 1`] = `
"\\"use strict\\";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
Expand All @@ -148,7 +151,10 @@ var AngularComponent = /** @class */ (function () {
}
AngularComponent = __decorate([
core_1.Component({
styleUrls: []
styles: [
'body { display: none }',
'html { background-color: red }'
]
})
], AngularComponent);
return AngularComponent;
Expand All @@ -157,7 +163,20 @@ exports.AngularComponent = AngularComponent;
"
`;

exports[`inlining template and stripping styles should strip styles assignment 1`] = `
exports[`inlining template and stripping styleUrls should not transform styles outside decorator 1`] = `
"var assignmentsToNotBeTransformed = {
styles: [{
color: 'red'
}]
};
var assignmentsToBeTransformed = {
styleUrls: [],
template: require('./some-styles.css')
};
"
`;

exports[`inlining template and stripping styleUrls should strip styleUrls assignment 1`] = `
"\\"use strict\\";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
Expand All @@ -172,7 +191,7 @@ var AngularComponent = /** @class */ (function () {
}
AngularComponent = __decorate([
core_1.Component({
styles: []
styleUrls: []
})
], AngularComponent);
return AngularComponent;
Expand Down
Loading

0 comments on commit 351e919

Please sign in to comment.