| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  | import {AbsoluteFsPath, resolve} from '@angular/compiler-cli/src/ngtsc/file_system'; | 
					
						
							|  |  |  | import {runInEachFileSystem} from '@angular/compiler-cli/src/ngtsc/file_system/testing'; | 
					
						
							| 
									
										
										
										
											2019-06-14 12:19:09 +02:00
										 |  |  | import {AbsoluteSourceSpan, IdentifierKind, IndexedComponent, TopLevelIdentifier} from '@angular/compiler-cli/src/ngtsc/indexer'; | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  | import {ParseSourceFile} from '@angular/compiler/src/compiler'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  | import {NgtscTestEnvironment} from './env'; | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  | runInEachFileSystem(() => { | 
					
						
							|  |  |  |   describe('ngtsc component indexing', () => { | 
					
						
							|  |  |  |     let env !: NgtscTestEnvironment; | 
					
						
							|  |  |  |     let testSourceFile: AbsoluteFsPath; | 
					
						
							|  |  |  |     let testTemplateFile: AbsoluteFsPath; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     beforeEach(() => { | 
					
						
							|  |  |  |       env = NgtscTestEnvironment.setup(); | 
					
						
							|  |  |  |       env.tsconfig(); | 
					
						
							|  |  |  |       testSourceFile = resolve(env.basePath, 'test.ts'); | 
					
						
							|  |  |  |       testTemplateFile = resolve(env.basePath, 'test.html'); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |     describe('indexing metadata', () => { | 
					
						
							|  |  |  |       it('should generate component metadata', () => { | 
					
						
							|  |  |  |         const componentContent = `
 | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  |         import {Component} from '@angular/core'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @Component({ | 
					
						
							|  |  |  |           selector: 'test-cmp', | 
					
						
							|  |  |  |           template: '<div></div>', | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         export class TestCmp {} | 
					
						
							|  |  |  |     `;
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |         env.write(testSourceFile, componentContent); | 
					
						
							|  |  |  |         const indexed = env.driveIndexer(); | 
					
						
							|  |  |  |         expect(indexed.size).toBe(1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const [[decl, indexedComp]] = Array.from(indexed.entries()); | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |         expect(decl.getText()).toContain('export class TestCmp {}'); | 
					
						
							| 
									
										
										
										
											2019-06-14 12:19:09 +02:00
										 |  |  |         expect(indexedComp).toEqual(jasmine.objectContaining<IndexedComponent>({ | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |           name: 'TestCmp', | 
					
						
							|  |  |  |           selector: 'test-cmp', | 
					
						
							|  |  |  |           file: new ParseSourceFile(componentContent, testSourceFile), | 
					
						
							|  |  |  |         })); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it('should index inline templates', () => { | 
					
						
							|  |  |  |         const componentContent = `
 | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  |         import {Component} from '@angular/core'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @Component({ | 
					
						
							|  |  |  |           selector: 'test-cmp', | 
					
						
							|  |  |  |           template: '{{foo}}', | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         export class TestCmp { foo = 0; } | 
					
						
							|  |  |  |       `;
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |         env.write(testSourceFile, componentContent); | 
					
						
							|  |  |  |         const indexed = env.driveIndexer(); | 
					
						
							|  |  |  |         const [[_, indexedComp]] = Array.from(indexed.entries()); | 
					
						
							|  |  |  |         const template = indexedComp.template; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(template).toEqual({ | 
					
						
							| 
									
										
										
										
											2019-07-03 15:10:40 -07:00
										 |  |  |           identifiers: new Set<TopLevelIdentifier>([{ | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |             name: 'foo', | 
					
						
							|  |  |  |             kind: IdentifierKind.Property, | 
					
						
							|  |  |  |             span: new AbsoluteSourceSpan(127, 130), | 
					
						
							| 
									
										
										
										
											2019-07-24 09:14:20 -07:00
										 |  |  |             target: null, | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |           }]), | 
					
						
							|  |  |  |           usedComponents: new Set(), | 
					
						
							|  |  |  |           isInline: true, | 
					
						
							|  |  |  |           file: new ParseSourceFile(componentContent, testSourceFile), | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |       it('should index external templates', () => { | 
					
						
							|  |  |  |         env.write(testSourceFile, `
 | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  |         import {Component} from '@angular/core'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @Component({ | 
					
						
							|  |  |  |           selector: 'test-cmp', | 
					
						
							|  |  |  |           templateUrl: './test.html', | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         export class TestCmp { foo = 0; } | 
					
						
							|  |  |  |       `);
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |         env.write(testTemplateFile, '{{foo}}'); | 
					
						
							|  |  |  |         const indexed = env.driveIndexer(); | 
					
						
							|  |  |  |         const [[_, indexedComp]] = Array.from(indexed.entries()); | 
					
						
							|  |  |  |         const template = indexedComp.template; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(template).toEqual({ | 
					
						
							| 
									
										
										
										
											2019-07-03 15:10:40 -07:00
										 |  |  |           identifiers: new Set<TopLevelIdentifier>([{ | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |             name: 'foo', | 
					
						
							|  |  |  |             kind: IdentifierKind.Property, | 
					
						
							|  |  |  |             span: new AbsoluteSourceSpan(2, 5), | 
					
						
							| 
									
										
										
										
											2019-07-24 09:14:20 -07:00
										 |  |  |             target: null, | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |           }]), | 
					
						
							|  |  |  |           usedComponents: new Set(), | 
					
						
							|  |  |  |           isInline: false, | 
					
						
							|  |  |  |           file: new ParseSourceFile('{{foo}}', testTemplateFile), | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |       it('should index templates compiled without preserving whitespace', () => { | 
					
						
							|  |  |  |         env.tsconfig({ | 
					
						
							|  |  |  |           preserveWhitespaces: false, | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |         env.write(testSourceFile, `
 | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  |         import {Component} from '@angular/core'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @Component({ | 
					
						
							|  |  |  |           selector: 'test-cmp', | 
					
						
							|  |  |  |           templateUrl: './test.html', | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         export class TestCmp { foo = 0; } | 
					
						
							|  |  |  |       `);
 | 
					
						
							| 
									
										
										
										
											2019-07-03 15:10:40 -07:00
										 |  |  |         env.write(testTemplateFile, '  \n  {{foo}}'); | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |         const indexed = env.driveIndexer(); | 
					
						
							|  |  |  |         const [[_, indexedComp]] = Array.from(indexed.entries()); | 
					
						
							|  |  |  |         const template = indexedComp.template; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         expect(template).toEqual({ | 
					
						
							| 
									
										
										
										
											2019-07-03 15:10:40 -07:00
										 |  |  |           identifiers: new Set<TopLevelIdentifier>([{ | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |             name: 'foo', | 
					
						
							|  |  |  |             kind: IdentifierKind.Property, | 
					
						
							| 
									
										
										
										
											2019-07-03 15:10:40 -07:00
										 |  |  |             span: new AbsoluteSourceSpan(7, 10), | 
					
						
							| 
									
										
										
										
											2019-07-24 09:14:20 -07:00
										 |  |  |             target: null, | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |           }]), | 
					
						
							|  |  |  |           usedComponents: new Set(), | 
					
						
							|  |  |  |           isInline: false, | 
					
						
							| 
									
										
										
										
											2019-07-03 15:10:40 -07:00
										 |  |  |           file: new ParseSourceFile('  \n  {{foo}}', testTemplateFile), | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |         }); | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |       it('should generate information about used components', () => { | 
					
						
							|  |  |  |         env.write(testSourceFile, `
 | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  |         import {Component} from '@angular/core'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @Component({ | 
					
						
							|  |  |  |           selector: 'test-cmp', | 
					
						
							|  |  |  |           templateUrl: './test.html', | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         export class TestCmp {} | 
					
						
							|  |  |  |       `);
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |         env.write(testTemplateFile, '<div></div>'); | 
					
						
							|  |  |  |         env.write('test_import.ts', `
 | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  |         import {Component, NgModule} from '@angular/core'; | 
					
						
							|  |  |  |         import {TestCmp} from './test'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @Component({ | 
					
						
							|  |  |  |           templateUrl: './test_import.html', | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         export class TestImportCmp {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @NgModule({ | 
					
						
							|  |  |  |           declarations: [ | 
					
						
							|  |  |  |             TestCmp, | 
					
						
							|  |  |  |             TestImportCmp, | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |           bootstrap: [TestImportCmp] | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         export class TestModule {} | 
					
						
							|  |  |  |       `);
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |         env.write('test_import.html', '<test-cmp></test-cmp>'); | 
					
						
							|  |  |  |         const indexed = env.driveIndexer(); | 
					
						
							|  |  |  |         expect(indexed.size).toBe(2); | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |         const indexedComps = Array.from(indexed.values()); | 
					
						
							|  |  |  |         const testComp = indexedComps.find(comp => comp.name === 'TestCmp'); | 
					
						
							|  |  |  |         const testImportComp = indexedComps.find(cmp => cmp.name === 'TestImportCmp'); | 
					
						
							|  |  |  |         expect(testComp).toBeDefined(); | 
					
						
							|  |  |  |         expect(testImportComp).toBeDefined(); | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |         expect(testComp !.template.usedComponents.size).toBe(0); | 
					
						
							|  |  |  |         expect(testImportComp !.template.usedComponents.size).toBe(1); | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-06 20:22:32 +01:00
										 |  |  |         const [usedComp] = Array.from(testImportComp !.template.usedComponents); | 
					
						
							|  |  |  |         expect(indexed.get(usedComp)).toEqual(testComp); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2019-06-19 17:23:59 -07:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); |