From e73e864f87eacf35b9bb25113193190e64566f25 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Thu, 23 Aug 2018 09:01:21 +0100 Subject: [PATCH] test(ivy): refactor Esm5Renderer tests to make them less fragile (#25534) PR Close #25534 --- .../ngcc/test/rendering/esm5_renderer_spec.ts | 219 +++++++----------- 1 file changed, 84 insertions(+), 135 deletions(-) diff --git a/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts b/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts index b3ab70ac32..e2653ca695 100644 --- a/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts +++ b/packages/compiler-cli/src/ngcc/test/rendering/esm5_renderer_spec.ts @@ -27,74 +27,85 @@ function analyze(parser: Esm5FileParser, analyzer: Analyzer, file: ts.SourceFile return parsedFiles.map(file => analyzer.analyzeFile(file))[0]; } +const PROGRAM = { + name: 'some/file.js', + contents: ` +/* A copyright notice */ +import {Directive} from '@angular/core'; +var A = (function() { + function A() {} + A.decorators = [ + { type: Directive, args: [{ selector: '[a]' }] }, + { type: OtherA } + ]; + return A; +}()); + +var B = (function() { + function B() {} + B.decorators = [ + { type: OtherB }, + { type: Directive, args: [{ selector: '[b]' }] } + ]; + return B; +}()); + +var C = (function() { + function C() {} + C.decorators = [ + { type: Directive, args: [{ selector: '[c]' }] }, + ]; + return C; +}()); + +// Some other content +export {A, B, C};` +}; + describe('Esm5Renderer', () => { 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 */ -import {Directive} from '@angular/core'; -var A = (function() { - function A() {} - A.decorators = [ - { type: Directive, args: [{ selector: '[a]' }] }, - { type: Other } - ]; - return A; -}()); -// Some other content -export {A};` - }; const {renderer} = setup(PROGRAM); const output = new MagicString(PROGRAM.contents); renderer.addImports( output, [{name: '@angular/core', as: 'i0'}, {name: '@angular/common', as: 'i1'}]); - expect(output.toString()) - .toEqual( - `import * as i0 from '@angular/core';\n` + - `import * as i1 from '@angular/common';\n` + PROGRAM.contents); + expect(output.toString()).toContain(`import * as i0 from '@angular/core'; +import * as i1 from '@angular/common'; + +/* A copyright notice */`); }); }); + describe('addConstants', () => { + it('should insert the given constants after imports in the source file', () => { + const {renderer, program} = setup(PROGRAM); + const file = program.getSourceFile('some/file.js'); + if (file === undefined) { + throw new Error(`Could not find source file`); + } + const output = new MagicString(PROGRAM.contents); + renderer.addConstants(output, 'const x = 3;', file); + expect(output.toString()).toContain(` +import {Directive} from '@angular/core'; +const x = 3; + +var A = (function() {`); + }); + }); + describe('addDefinitions', () => { 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'; -var A = (function() { - function A() {} - A.decorators = [ - { type: Directive, args: [{ selector: '[a]' }] }, - { type: Other } - ]; - return A; -}()); -// Some other content -export {A};` - }; const {analyzer, parser, program, renderer} = setup(PROGRAM); const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !); const output = new MagicString(PROGRAM.contents); renderer.addDefinitions(output, analyzedFile.analyzedClasses[0], 'SOME DEFINITION TEXT'); - expect(output.toString()).toEqual(` -/* A copyright notice */ -import {Directive} from '@angular/core'; -var A = (function() { + expect(output.toString()).toContain(` function A() {} SOME DEFINITION TEXT A.decorators = [ - { type: Directive, args: [{ selector: '[a]' }] }, - { type: Other } - ]; - return A; -}()); -// Some other content -export {A};`); +`); }); }); @@ -103,120 +114,58 @@ export {A};`); describe('removeDecorators', () => { 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'; -var A = (function() { - function A() {} - A.decorators = [ - { type: Directive, args: [{ selector: '[a]' }] }, - { type: Other } - ]; - return A; -}()); -// Some other content -export {A};` - }; const {analyzer, parser, program, renderer} = setup(PROGRAM); const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !); const output = new MagicString(PROGRAM.contents); const analyzedClass = analyzedFile.analyzedClasses[0]; + const decorator = analyzedClass.decorators[0]; const decoratorsToRemove = new Map(); - decoratorsToRemove.set( - analyzedClass.decorators[0].node.parent !, [analyzedClass.decorators[0].node]); + decoratorsToRemove.set(decorator.node.parent !, [decorator.node]); renderer.removeDecorators(output, decoratorsToRemove); - expect(output.toString()).toEqual(` -/* A copyright notice */ -import {Directive} from '@angular/core'; -var A = (function() { - function A() {} - A.decorators = [ - { type: Other } - ]; - return A; -}()); -// Some other content -export {A};`); + expect(output.toString()).not.toContain(`{ type: Directive, args: [{ selector: '[a]' }] },`); + expect(output.toString()).toContain(`{ type: OtherA }`); + expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[b]' }] }`); + expect(output.toString()).toContain(`{ type: OtherB }`); + expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[c]' }] }`); }); 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'; -var A = (function() { - function A() {} - A.decorators = [ - { type: Other }, - { type: Directive, args: [{ selector: '[a]' }] } - ]; - return A; -}()); -// Some other content -export {A};` - }; const {analyzer, parser, program, renderer} = setup(PROGRAM); const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !); 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(); - decoratorsToRemove.set( - analyzedClass.decorators[0].node.parent !, [analyzedClass.decorators[1].node]); + decoratorsToRemove.set(decorator.node.parent !, [decorator.node]); renderer.removeDecorators(output, decoratorsToRemove); - expect(output.toString()).toEqual(` -/* A copyright notice */ -import {Directive} from '@angular/core'; -var A = (function() { - function A() {} - A.decorators = [ - { type: Other }, - ]; - return A; -}()); -// Some other content -export {A};`); + expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[a]' }] },`); + expect(output.toString()).toContain(`{ type: OtherA }`); + expect(output.toString()) + .not.toContain(`{ type: Directive, args: [{ selector: '[b]' }] }`); + expect(output.toString()).toContain(`{ type: OtherB }`); + expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[c]' }] }`); }); 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'; -var A = (function() { - function A() {} - A.decorators = [ - { type: Directive, args: [{ selector: '[a]' }] } - ]; - return A; -}()); -// Some other content -export {A};` - }; const {analyzer, parser, program, renderer} = setup(PROGRAM); const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !); 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(); - decoratorsToRemove.set( - analyzedClass.decorators[0].node.parent !, [analyzedClass.decorators[0].node]); + decoratorsToRemove.set(decorator.node.parent !, [decorator.node]); renderer.removeDecorators(output, decoratorsToRemove); - expect(output.toString()).toEqual(` -/* A copyright notice */ -import {Directive} from '@angular/core'; -var A = (function() { - function A() {} - return A; -}()); -// Some other content -export {A};`); + expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[a]' }] },`); + expect(output.toString()).toContain(`{ type: OtherA }`); + expect(output.toString()).toContain(`{ type: Directive, args: [{ selector: '[b]' }] }`); + expect(output.toString()).toContain(`{ type: OtherB }`); + expect(output.toString()).not.toContain(`C.decorators = [ + { type: Directive, args: [{ selector: '[c]' }] }, +];`); }); });