diff --git a/packages/angular/src/utils/ast-utils.spec.ts b/packages/angular/src/utils/ast-utils.spec.ts new file mode 100644 index 0000000000..1ba479a187 --- /dev/null +++ b/packages/angular/src/utils/ast-utils.spec.ts @@ -0,0 +1,112 @@ +import { InsertChange } from '@nrwl/workspace/src/utils/ast-utils'; +import { createSourceFile, ScriptTarget } from 'typescript'; +import { addProviderToModule } from './ast-utils'; + +describe('ast-utils', () => { + describe('_addSymbolToNgModuleMetadata', () => { + const moduleImport = `import { NgModule } from '@angular/core';`; + const fileName = 'app.module.ts'; + const createTemplate = (content: string, close: string) => ({ + start: content.length, + text: content + close + }); + const createStockModule = (content: string) => + createSourceFile(fileName, content, ScriptTarget.Latest, true); + + it('should add provider to module without existing providers', () => { + const toAdd = 'MyProvider'; + + const { start, text } = createTemplate( + moduleImport + '@NgModule({', + '})' + ); + const source = createStockModule(text); + const change = addProviderToModule(source, fileName, toAdd); + const expectedChange = [ + new InsertChange(fileName, start, ` providers: [${toAdd}]\n`) + ]; + + expect(change).toEqual(expectedChange); + }); + + it('should add provider to module with existing empty providers', () => { + const toAdd = 'MyProvider'; + + const { start, text } = createTemplate( + moduleImport + '@NgModule({providers:[', + ']})' + ); + const source = createStockModule(text); + const change = addProviderToModule(source, fileName, toAdd); + const expectedChange = [new InsertChange(fileName, start, toAdd)]; + + expect(change).toEqual(expectedChange); + }); + + it('should add provider to module with existing providers', () => { + const toAdd = 'MyProvider'; + + let template = createTemplate( + moduleImport + '@NgModule({providers:[ProviderOne,ProviderTwo', + ']})' + ); + let source = createStockModule(template.text); + let change = addProviderToModule(source, fileName, toAdd); + let expectedChange = [ + new InsertChange(fileName, template.start, `, ${toAdd}`) + ]; + + expect(change).toEqual(expectedChange); + + template = createTemplate( + moduleImport + + '@NgModule({providers:[{provide:MyClass,useExisting:MyExistingClass}', + ']})' + ); + source = createStockModule(template.text); + change = addProviderToModule(source, fileName, toAdd); + expectedChange = [ + new InsertChange(fileName, template.start, `, ${toAdd}`) + ]; + + expect(change).toEqual(expectedChange); + + template = createTemplate( + moduleImport + '@NgModule({providers:[someCondition ? MyProvider : []', + ']})' + ); + source = createStockModule(template.text); + change = addProviderToModule(source, fileName, toAdd); + expectedChange = [ + new InsertChange(fileName, template.start, `, ${toAdd}`) + ]; + + expect(change).toEqual(expectedChange); + + template = createTemplate( + moduleImport + + '@NgModule({providers:[[NestedProvider1, NestedProvider2]', + ']})' + ); + source = createStockModule(template.text); + change = addProviderToModule(source, fileName, toAdd); + expectedChange = [ + new InsertChange(fileName, template.start, `, ${toAdd}`) + ]; + + expect(change).toEqual(expectedChange); + + template = createTemplate( + moduleImport + '@NgModule({providers:[...ExistingProviders', + ']})' + ); + source = createStockModule(template.text); + change = addProviderToModule(source, fileName, toAdd); + expectedChange = [ + new InsertChange(fileName, template.start, `, ${toAdd}`) + ]; + + expect(change).toEqual(expectedChange); + }); + }); +}); diff --git a/packages/angular/src/utils/ast-utils.ts b/packages/angular/src/utils/ast-utils.ts index 991a60b8e2..1137b437b0 100644 --- a/packages/angular/src/utils/ast-utils.ts +++ b/packages/angular/src/utils/ast-utils.ts @@ -216,7 +216,8 @@ function _addSymbolToNgModuleMetadata( return []; } - if (Array.isArray(node)) { + const isArray = Array.isArray(node); + if (isArray) { const nodeArray = (node as {}) as Array; const symbolsArray = nodeArray.map(node => node.getText()); if (symbolsArray.includes(expression)) { @@ -228,7 +229,7 @@ function _addSymbolToNgModuleMetadata( let toInsert: string; let position = node.getEnd(); - if (node.kind == ts.SyntaxKind.ObjectLiteralExpression) { + if (!isArray && node.kind == ts.SyntaxKind.ObjectLiteralExpression) { // We haven't found the field in the metadata declaration. Insert a new // field. const expr = node as ts.ObjectLiteralExpression; @@ -248,7 +249,7 @@ function _addSymbolToNgModuleMetadata( toInsert = `, ${metadataField}: [${expression}]`; } } - } else if (node.kind == ts.SyntaxKind.ArrayLiteralExpression) { + } else if (!isArray && node.kind == ts.SyntaxKind.ArrayLiteralExpression) { // We found the field but it's empty. Insert it just before the `]`. position--; toInsert = `${expression}`;