test(ivy): refactor Esm2015Renderer tests to make them less fragile (#25534)

PR Close #25534
This commit is contained in:
Pete Bacon Darwin 2018-08-17 07:35:01 +01:00 committed by Misko Hevery
parent 6f168b7a0f
commit 73047483a1
1 changed files with 51 additions and 109 deletions

View File

@ -27,49 +27,46 @@ function analyze(parser: Esm2015FileParser, analyzer: Analyzer, file: ts.SourceF
return parsedFiles.map(file => analyzer.analyzeFile(file))[0]; return parsedFiles.map(file => analyzer.analyzeFile(file))[0];
} }
const PROGRAM = {
describe('Esm2015Renderer', () => { name: 'some/file.js',
contents: `
describe('addImports', () => {
it('should insert the given imports at the start of the source file', () => {
const PROGRAM = {
name: 'some/file.js',
contents: `
/* A copyright notice */ /* A copyright notice */
import {Directive} from '@angular/core'; import {Directive} from '@angular/core';
export class A {} export class A {}
A.decorators = [ A.decorators = [
{ type: Directive, args: [{ selector: '[a]' }] }, { type: Directive, args: [{ selector: '[a]' }] },
{ type: Other } { type: OtherA }
];
export class B {}
B.decorators = [
{ type: OtherB },
{ type: Directive, args: [{ selector: '[b]' }] }
];
export class C {}
C.decorators = [
{ type: Directive, args: [{ selector: '[c]' }] },
]; ];
// Some other content` // Some other content`
}; };
describe('Esm2015Renderer', () => {
describe('addImports', () => {
it('should insert the given imports at the start of the source file', () => {
const {renderer} = setup(PROGRAM); const {renderer} = setup(PROGRAM);
const output = new MagicString(PROGRAM.contents); const output = new MagicString(PROGRAM.contents);
renderer.addImports( renderer.addImports(
output, [{name: '@angular/core', as: 'i0'}, {name: '@angular/common', as: 'i1'}]); output, [{name: '@angular/core', as: 'i0'}, {name: '@angular/common', as: 'i1'}]);
expect(output.toString()) expect(output.toString()).toContain(`import * as i0 from '@angular/core';
.toEqual( import * as i1 from '@angular/common';
`import * as i0 from '@angular/core';\n` +
`import * as i1 from '@angular/common';\n` + PROGRAM.contents); /* A copyright notice */`);
}); });
}); });
describe('addConstants', () => { describe('addConstants', () => {
it('should insert the given constants after imports in the source file', () => { it('should insert the given constants after imports in the source file', () => {
const PROGRAM = {
name: 'some/file.js',
contents: `
/* A copyright notice */
import {Directive} from '@angular/core';
export class A {}
A.decorators = [
{ type: Directive, args: [{ selector: '[a]' }] },
{ type: Other }
];
// Some other content`
};
const {renderer, program} = setup(PROGRAM); const {renderer, program} = setup(PROGRAM);
const file = program.getSourceFile('some/file.js'); const file = program.getSourceFile('some/file.js');
if (file === undefined) { if (file === undefined) {
@ -88,32 +85,15 @@ export class A {}`);
describe('addDefinitions', () => { describe('addDefinitions', () => {
it('should insert the definitions directly after the class declaration', () => { it('should insert the definitions directly after the class declaration', () => {
const PROGRAM = {
name: 'some/file.js',
contents: `
/* A copyright notice */
import {Directive} from '@angular/core';
export class A {}
A.decorators = [
{ type: Directive, args: [{ selector: '[a]' }] },
{ type: Other }
];
// Some other content`
};
const {analyzer, parser, program, renderer} = setup(PROGRAM); const {analyzer, parser, program, renderer} = setup(PROGRAM);
const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !); const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !);
const output = new MagicString(PROGRAM.contents); const output = new MagicString(PROGRAM.contents);
renderer.addDefinitions(output, analyzedFile.analyzedClasses[0], 'SOME DEFINITION TEXT'); renderer.addDefinitions(output, analyzedFile.analyzedClasses[0], 'SOME DEFINITION TEXT');
expect(output.toString()).toEqual(` expect(output.toString()).toContain(`
/* A copyright notice */
import {Directive} from '@angular/core';
export class A {} export class A {}
SOME DEFINITION TEXT SOME DEFINITION TEXT
A.decorators = [ A.decorators = [
{ type: Directive, args: [{ selector: '[a]' }] }, `);
{ type: Other }
];
// Some other content`);
}); });
}); });
@ -122,96 +102,58 @@ A.decorators = [
describe('removeDecorators', () => { describe('removeDecorators', () => {
it('should delete the decorator (and following comma) that was matched in the analysis', () => { it('should delete the decorator (and following comma) that was matched in the analysis', () => {
const PROGRAM = {
name: 'some/file.js',
contents: `
/* A copyright notice */
import {Directive} from '@angular/core';
export class A {}
A.decorators = [
{ type: Directive, args: [{ selector: '[a]' }] },
{ type: Other }
];
// Some other content`
};
const {analyzer, parser, program, renderer} = setup(PROGRAM); const {analyzer, parser, program, renderer} = setup(PROGRAM);
const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !); const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !);
const output = new MagicString(PROGRAM.contents); const output = new MagicString(PROGRAM.contents);
const analyzedClass = analyzedFile.analyzedClasses[0]; const analyzedClass = analyzedFile.analyzedClasses[0];
const decorator = analyzedClass.decorators[0];
const decoratorsToRemove = new Map<ts.Node, ts.Node[]>(); const decoratorsToRemove = new Map<ts.Node, ts.Node[]>();
decoratorsToRemove.set( decoratorsToRemove.set(decorator.node.parent !, [decorator.node]);
analyzedClass.decorators[0].node.parent !, [analyzedClass.decorators[0].node]);
renderer.removeDecorators(output, decoratorsToRemove); renderer.removeDecorators(output, decoratorsToRemove);
expect(output.toString()).toEqual(` expect(output.toString()).not.toContain(`{ type: Directive, args: [{ selector: '[a]' }] },`);
/* A copyright notice */ expect(output.toString()).toContain(`{ type: OtherA }`);
import {Directive} from '@angular/core'; expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[b]' }] }`);
export class A {} expect(output.toString()).toContain(`{ type: OtherB }`);
A.decorators = [ expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[c]' }] }`);
{ type: Other }
];
// Some other content`);
}); });
it('should delete the decorator (but cope with no trailing comma) that was matched in the analysis', it('should delete the decorator (but cope with no trailing comma) that was matched in the analysis',
() => { () => {
const PROGRAM = {
name: 'some/file.js',
contents: `
/* A copyright notice */
import {Directive} from '@angular/core';
export class A {}
A.decorators = [
{ type: Other },
{ type: Directive, args: [{ selector: '[a]' }] }
];
// Some other content`
};
const {analyzer, parser, program, renderer} = setup(PROGRAM); const {analyzer, parser, program, renderer} = setup(PROGRAM);
const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !); const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !);
const output = new MagicString(PROGRAM.contents); const output = new MagicString(PROGRAM.contents);
const analyzedClass = analyzedFile.analyzedClasses[0]; const analyzedClass = analyzedFile.analyzedClasses[1];
const decorator = analyzedClass.decorators[1];
const decoratorsToRemove = new Map<ts.Node, ts.Node[]>(); const decoratorsToRemove = new Map<ts.Node, ts.Node[]>();
decoratorsToRemove.set( decoratorsToRemove.set(decorator.node.parent !, [decorator.node]);
analyzedClass.decorators[0].node.parent !, [analyzedClass.decorators[1].node]);
renderer.removeDecorators(output, decoratorsToRemove); renderer.removeDecorators(output, decoratorsToRemove);
expect(output.toString()).toEqual(` expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[a]' }] },`);
/* A copyright notice */ expect(output.toString()).toContain(`{ type: OtherA }`);
import {Directive} from '@angular/core'; expect(output.toString())
export class A {} .not.toContain(`{ type: Directive, args: [{ selector: '[b]' }] }`);
A.decorators = [ expect(output.toString()).toContain(`{ type: OtherB }`);
{ type: Other }, expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[c]' }] }`);
];
// Some other content`);
}); });
it('should delete the decorator (and its container if there are not other decorators left) that was matched in the analysis', it('should delete the decorator (and its container if there are not other decorators left) that was matched in the analysis',
() => { () => {
const PROGRAM = {
name: 'some/file.js',
contents: `
/* A copyright notice */
import {Directive} from '@angular/core';
export class A {}
A.decorators = [
{ type: Directive, args: [{ selector: '[a]' }] }
];
// Some other content`
};
const {analyzer, parser, program, renderer} = setup(PROGRAM); const {analyzer, parser, program, renderer} = setup(PROGRAM);
const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !); const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !);
const output = new MagicString(PROGRAM.contents); const output = new MagicString(PROGRAM.contents);
const analyzedClass = analyzedFile.analyzedClasses[0]; const analyzedClass = analyzedFile.analyzedClasses[2];
const decorator = analyzedClass.decorators[0];
const decoratorsToRemove = new Map<ts.Node, ts.Node[]>(); const decoratorsToRemove = new Map<ts.Node, ts.Node[]>();
decoratorsToRemove.set( decoratorsToRemove.set(decorator.node.parent !, [decorator.node]);
analyzedClass.decorators[0].node.parent !, [analyzedClass.decorators[0].node]);
renderer.removeDecorators(output, decoratorsToRemove); renderer.removeDecorators(output, decoratorsToRemove);
expect(output.toString()).toEqual(` expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[a]' }] },`);
/* A copyright notice */ expect(output.toString()).toContain(`{ type: OtherA }`);
import {Directive} from '@angular/core'; expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[b]' }] }`);
export class A {} expect(output.toString()).toContain(`{ type: OtherB }`);
// Some other content`); expect(output.toString()).not.toContain(`C.decorators = [
{ type: Directive, args: [{ selector: '[c]' }] },
];`);
}); });
}); });