Also reenabled tests that were unintentionally disabled when they were moved from tools/@angular.
		
			
				
	
	
		
			134 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			134 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /**
 | |
|  * @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
 | |
|  */
 | |
| 
 | |
| import * as ts from 'typescript';
 | |
| 
 | |
| import {isMetadataGlobalReferenceExpression} from '../src/schema';
 | |
| import {Symbols} from '../src/symbols';
 | |
| 
 | |
| import {Directory, Host, expectNoDiagnostics} from './typescript.mocks';
 | |
| 
 | |
| describe('Symbols', () => {
 | |
|   let symbols: Symbols;
 | |
|   const someValue = 'some-value';
 | |
| 
 | |
|   beforeEach(() => symbols = new Symbols(null as any as ts.SourceFile));
 | |
| 
 | |
|   it('should be able to add a symbol', () => symbols.define('someSymbol', someValue));
 | |
| 
 | |
|   beforeEach(() => symbols.define('someSymbol', someValue));
 | |
| 
 | |
|   it('should be able to `has` a symbol', () => expect(symbols.has('someSymbol')).toBeTruthy());
 | |
|   it('should be able to `get` a symbol value',
 | |
|      () => expect(symbols.resolve('someSymbol')).toBe(someValue));
 | |
|   it('should be able to `get` a symbol value',
 | |
|      () => expect(symbols.resolve('someSymbol')).toBe(someValue));
 | |
|   it('should be able to determine symbol is missing',
 | |
|      () => expect(symbols.has('missingSymbol')).toBeFalsy());
 | |
|   it('should return undefined from `get` for a missing symbol',
 | |
|      () => expect(symbols.resolve('missingSymbol')).toBeUndefined());
 | |
| 
 | |
|   let host: ts.LanguageServiceHost;
 | |
|   let service: ts.LanguageService;
 | |
|   let program: ts.Program;
 | |
|   let expressions: ts.SourceFile;
 | |
|   let imports: ts.SourceFile;
 | |
| 
 | |
|   beforeEach(() => {
 | |
|     host = new Host(FILES, ['consts.ts', 'expressions.ts', 'imports.ts']);
 | |
|     service = ts.createLanguageService(host);
 | |
|     program = service.getProgram();
 | |
|     expressions = program.getSourceFile('expressions.ts');
 | |
|     imports = program.getSourceFile('imports.ts');
 | |
|   });
 | |
| 
 | |
|   it('should not have syntax errors in the test sources', () => {
 | |
|     expectNoDiagnostics(service.getCompilerOptionsDiagnostics());
 | |
|     for (const sourceFile of program.getSourceFiles()) {
 | |
|       expectNoDiagnostics(service.getSyntacticDiagnostics(sourceFile.fileName));
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   it('should be able to find the source files', () => {
 | |
|     expect(expressions).toBeDefined();
 | |
|     expect(imports).toBeDefined();
 | |
|   });
 | |
| 
 | |
|   it('should be able to create symbols for a source file', () => {
 | |
|     const symbols = new Symbols(expressions);
 | |
|     expect(symbols).toBeDefined();
 | |
|   });
 | |
| 
 | |
| 
 | |
|   it('should be able to find symbols in expression', () => {
 | |
|     const symbols = new Symbols(expressions);
 | |
|     expect(symbols.has('someName')).toBeTruthy();
 | |
|     expect(symbols.resolve('someName'))
 | |
|         .toEqual({__symbolic: 'reference', module: './consts', name: 'someName'});
 | |
|     expect(symbols.has('someBool')).toBeTruthy();
 | |
|     expect(symbols.resolve('someBool'))
 | |
|         .toEqual({__symbolic: 'reference', module: './consts', name: 'someBool'});
 | |
|   });
 | |
| 
 | |
|   it('should be able to detect a * import', () => {
 | |
|     const symbols = new Symbols(imports);
 | |
|     expect(symbols.resolve('b')).toEqual({__symbolic: 'reference', module: 'b'});
 | |
|   });
 | |
| 
 | |
|   it('should be able to detect importing a default export', () => {
 | |
|     const symbols = new Symbols(imports);
 | |
|     expect(symbols.resolve('d')).toEqual({__symbolic: 'reference', module: 'd', default: true});
 | |
|   });
 | |
| 
 | |
|   it('should be able to import a renamed symbol', () => {
 | |
|     const symbols = new Symbols(imports);
 | |
|     expect(symbols.resolve('g')).toEqual({__symbolic: 'reference', name: 'f', module: 'f'});
 | |
|   });
 | |
| 
 | |
|   it('should be able to resolve any symbol in core global scope', () => {
 | |
|     const core = program.getSourceFiles().find(source => source.fileName.endsWith('lib.d.ts'));
 | |
|     expect(core).toBeDefined();
 | |
|     const visit = (node: ts.Node): boolean => {
 | |
|       switch (node.kind) {
 | |
|         case ts.SyntaxKind.VariableStatement:
 | |
|         case ts.SyntaxKind.VariableDeclarationList:
 | |
|           return ts.forEachChild(node, visit);
 | |
|         case ts.SyntaxKind.VariableDeclaration:
 | |
|           const variableDeclaration = <ts.VariableDeclaration>node;
 | |
|           const nameNode = <ts.Identifier>variableDeclaration.name;
 | |
|           const name = nameNode.text;
 | |
|           const result = symbols.resolve(name);
 | |
|           expect(isMetadataGlobalReferenceExpression(result) && result.name).toEqual(name);
 | |
| 
 | |
|           // Ignore everything after Float64Array as it is IE specific.
 | |
|           return name === 'Float64Array';
 | |
|       }
 | |
|       return false;
 | |
|     };
 | |
|     ts.forEachChild(core !, visit);
 | |
|   });
 | |
| });
 | |
| 
 | |
| const FILES: Directory = {
 | |
|   'consts.ts': `
 | |
|     export var someName = 'some-name';
 | |
|     export var someBool = true;
 | |
|     export var one = 1;
 | |
|     export var two = 2;
 | |
|   `,
 | |
|   'expressions.ts': `
 | |
|     import {someName, someBool, one, two} from './consts';
 | |
|   `,
 | |
|   'imports.ts': `
 | |
|     import * as b from 'b';
 | |
|     import 'c';
 | |
|     import d from 'd';
 | |
|     import {f as g} from 'f';
 | |
|   `
 | |
| };
 |