test(language-service): remove MockData from MockTypescriptHost (#32752)

Remove MockData from the constructor parameters of MockTypescriptHost
since the entire Tour of Heroes (TOH) project is now loaded from disk.

Added a new method `reset()` to MockTypescriptHost that is necessary to
reset the state of the project before each spec if run to make sure
previous overrides are cleared.

PR Close #32752
This commit is contained in:
Keen Yee Liau 2019-09-17 14:33:41 -07:00 committed by Andrew Kushnir
parent 0450f39625
commit f3859ff2b9
12 changed files with 64 additions and 343 deletions

View File

@ -11,15 +11,16 @@ import * as ts from 'typescript';
import {createLanguageService} from '../src/language_service';
import {TypeScriptServiceHost} from '../src/typescript_host';
import {toh} from './test_data';
import {MockTypescriptHost} from './test_utils';
describe('completions', () => {
let mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts'], toh);
let mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts']);
let service = ts.createLanguageService(mockHost);
let ngHost = new TypeScriptServiceHost(mockHost, service);
let ngService = createLanguageService(ngHost);
beforeEach(() => { mockHost.reset(); });
it('should be able to get entity completions',
() => { expectContains('/app/test.ng', 'entity-amp', '&', '>', '<', 'ι'); });
@ -44,7 +45,6 @@ describe('completions', () => {
const fileName = '/app/test.ng';
mockHost.override(fileName, ' > {{tle<\n {{retl ><bel/beled}}di>\n la</b </d &a ');
expect(() => ngService.getCompletionsAt(fileName, 31)).not.toThrow();
mockHost.override(fileName, undefined !);
});
it('should be able to infer the type of a ngForOf', () => {
@ -68,7 +68,7 @@ describe('completions', () => {
street: string
}
@Component({template: '<div *ngFor="let person of people | async">{{person.~{name}name}}</div'})
@Component({template: '<div *ngFor="let person of people | async">{{person.~{name}name}}</div>'})
export class MyComponent {
people: Promise<Person[]>;
}`);
@ -92,7 +92,7 @@ describe('completions', () => {
throw e;
}
}
try {
const originalContent = mockHost.getFileContent(fileName) !;
// For each character in the file, add it to the file and request a completion after it.
@ -124,9 +124,6 @@ describe('completions', () => {
mockHost.override(fileName, text);
tryCompletionsAt(position);
});
} finally {
mockHost.override(fileName, undefined !);
}
}).not.toThrow();
});

View File

@ -12,7 +12,6 @@ import {createLanguageService} from '../src/language_service';
import {LanguageService} from '../src/types';
import {TypeScriptServiceHost} from '../src/typescript_host';
import {toh} from './test_data';
import {MockTypescriptHost} from './test_utils';
describe('definitions', () => {
@ -23,7 +22,7 @@ describe('definitions', () => {
beforeEach(() => {
// Create a new mockHost every time to reset any files that are overridden.
mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts'], toh);
mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts']);
service = ts.createLanguageService(mockHost);
ngHost = new TypeScriptServiceHost(mockHost, service);
ngService = createLanguageService(ngHost);

View File

@ -10,7 +10,6 @@ import * as ts from 'typescript';
import {createLanguageService} from '../src/language_service';
import * as ng from '../src/types';
import {TypeScriptServiceHost} from '../src/typescript_host';
import {toh} from './test_data';
import {MockTypescriptHost} from './test_utils';
/**
@ -32,7 +31,7 @@ describe('diagnostics', () => {
let ngLS: ng.LanguageService;
beforeEach(() => {
mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts'], toh);
mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts']);
tsLS = ts.createLanguageService(mockHost);
ngHost = new TypeScriptServiceHost(mockHost, tsLS);
ngLS = createLanguageService(ngHost);

View File

@ -12,7 +12,6 @@ import {createLanguageService} from '../src/language_service';
import {LanguageService} from '../src/types';
import {TypeScriptServiceHost} from '../src/typescript_host';
import {toh} from './test_data';
import {MockTypescriptHost} from './test_utils';
describe('hover', () => {
@ -22,7 +21,7 @@ describe('hover', () => {
let ngLS: LanguageService;
beforeEach(() => {
mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts'], toh);
mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts']);
tsLS = ts.createLanguageService(mockHost);
ngLSHost = new TypeScriptServiceHost(mockHost, tsLS);
ngLS = createLanguageService(ngLSHost);

View File

@ -11,11 +11,10 @@ import * as ts from 'typescript';
import {createLanguageService} from '../src/language_service';
import {TypeScriptServiceHost} from '../src/typescript_host';
import {toh} from './test_data';
import {MockTypescriptHost} from './test_utils';
describe('service without angular', () => {
let mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts'], toh);
let mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts']);
mockHost.forgetAngular();
let service = ts.createLanguageService(mockHost);
let ngHost = new TypeScriptServiceHost(mockHost, service);

View File

@ -9,11 +9,9 @@
import * as path from 'path';
import * as ts from 'typescript';
import {createLanguageService} from '../src/language_service';
import {ReflectorHost} from '../src/reflector_host';
import {TypeScriptServiceHost} from '../src/typescript_host';
import {toh} from './test_data';
import {MockTypescriptHost} from './test_utils';
describe('reflector_host_spec', () => {
@ -23,7 +21,7 @@ describe('reflector_host_spec', () => {
const originalJoin = path.join;
const originalPosixJoin = path.posix.join;
const mockHost =
new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts'], toh, 'node_modules', {
new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts'], 'node_modules', {
...path,
join: (...args: string[]) => originalJoin.apply(path, args),
posix:
@ -42,7 +40,7 @@ describe('reflector_host_spec', () => {
});
it('should use module resolution cache', () => {
const mockHost = new MockTypescriptHost(['/app/main.ts'], toh);
const mockHost = new MockTypescriptHost(['/app/main.ts']);
// TypeScript relies on `ModuleResolutionHost.fileExists()` to perform
// module resolution, so spy on this method to determine how many times
// it's called.

View File

@ -12,7 +12,6 @@ import {createLanguageService} from '../src/language_service';
import {LanguageService} from '../src/types';
import {TypeScriptServiceHost} from '../src/typescript_host';
import {toh} from './test_data';
import {MockTypescriptHost} from './test_utils';
describe('references', () => {
@ -23,7 +22,7 @@ describe('references', () => {
let ngService: LanguageService = createLanguageService(undefined !);
beforeEach(() => {
mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts'], toh);
mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts']);
service = ts.createLanguageService(mockHost, documentRegistry);
ngHost = new TypeScriptServiceHost(mockHost, service);
ngService = createLanguageService(ngHost);

View File

@ -8,7 +8,6 @@
import * as ts from 'typescript';
import {getClassDeclFromDecoratorProp} from '../src/template';
import {toh} from './test_data';
import {MockTypescriptHost} from './test_utils';
describe('getClassDeclFromTemplateNode', () => {
@ -35,7 +34,7 @@ describe('getClassDeclFromTemplateNode', () => {
it('should return class declaration for AppComponent', () => {
const host = new MockTypescriptHost(['/app/app.component.ts'], toh);
const host = new MockTypescriptHost(['/app/app.component.ts']);
const tsLS = ts.createLanguageService(host);
const sourceFile = tsLS.getProgram() !.getSourceFile('/app/app.component.ts');
expect(sourceFile).toBeTruthy();

View File

@ -1,242 +0,0 @@
/**
* @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
*/
export const toh = {
'foo.ts': `export * from './app/app.component.ts';`,
app: {
'app.component.ts': `import { Component, NgModule } from '@angular/core';
export class Hero {
id: number;
name: string;
}
@Component({
selector: 'my-app',
template: \`~{empty}
<~{start-tag}h~{start-tag-after-h}1~{start-tag-h1} ~{h1-after-space}>~{h1-content} {{~{sub-start}title~{sub-end}}}</h1>
~{after-h1}<h2>{{~{h2-hero}hero.~{h2-name}name}} details!</h2>
<div><label>id: </label>{{~{label-hero}hero.~{label-id}id}}</div>
<div ~{div-attributes}>
<label>name: </label>
</div>
&~{entity-amp}amp;
\`
})
export class AppComponent {
title = 'Tour of Heroes';
hero: Hero = {
id: 1,
name: 'Windstorm'
};
private internal: string;
}`,
'main.ts': `
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { CaseIncompleteOpen, CaseMissingClosing, CaseUnknown, Pipes, TemplateReference, NoValueAttribute,
AttributeBinding, StringModel, NumberModel, PropertyBinding, EventBinding, TwoWayBinding, EmptyInterpolation,
ForOfEmpty, ForLetIEqual, ForOfLetEmpty, ForUsingComponent, References, TestComponent} from './parsing-cases';
import { WrongFieldReference, WrongSubFieldReference, PrivateReference, ExpectNumericType, LowercasePipe } from './expression-cases';
import { UnknownPeople, UnknownEven, UnknownTrackBy } from './ng-for-cases';
import { ShowIf } from './ng-if-cases';
@NgModule({
imports: [CommonModule, FormsModule],
declarations: [AppComponent, CaseIncompleteOpen, CaseMissingClosing, CaseUnknown, Pipes, TemplateReference, NoValueAttribute,
AttributeBinding, StringModel, NumberModel, PropertyBinding, EventBinding, TwoWayBinding, EmptyInterpolation, ForOfEmpty, ForOfLetEmpty,
ForLetIEqual, ForUsingComponent, References, TestComponent, WrongFieldReference, WrongSubFieldReference, PrivateReference,
ExpectNumericType, UnknownPeople, UnknownEven, UnknownTrackBy, ShowIf, LowercasePipe]
})
export class AppModule {}
declare function bootstrap(v: any): void;
bootstrap(AppComponent);
`,
'parsing-cases.ts': `
import {Component, Directive, Input, Output, EventEmitter} from '@angular/core';
import {Hero} from './app.component';
@Component({template: '<h1>Some <~{incomplete-open-lt}a~{incomplete-open-a} ~{incomplete-open-attr} text</h1>'})
export class CaseIncompleteOpen {}
@Component({template: '<h1>Some <a> ~{missing-closing} text</h1>'})
export class CaseMissingClosing {}
@Component({template: '<h1>Some <unknown ~{unknown-element}> text</h1>'})
export class CaseUnknown {}
@Component({template: '<h1>{{data | ~{before-pipe}lowe~{in-pipe}rcase~{after-pipe} }}'})
export class Pipes {
data = 'Some string';
}
@Component({template: '<h1 h~{no-value-attribute}></h1>'})
export class NoValueAttribute {}
@Component({template: '<h1 model="~{attribute-binding-model}test"></h1>'})
export class AttributeBinding {
test: string;
}
@Component({template: '<h1 [model]="~{property-binding-model}test"></h1>'})
export class PropertyBinding {
test: string;
}
@Component({template: '<h1 (model)="~{event-binding-model}modelChanged()"></h1>'})
export class EventBinding {
test: string;
modelChanged() {}
}
@Component({template: '<h1 [(model)]="~{two-way-binding-model}test"></h1>'})
export class TwoWayBinding {
test: string;
}
@Directive({selector: '[string-model]'})
export class StringModel {
@Input() model: string;
@Output() modelChanged: EventEmitter<string>;
}
@Directive({selector: '[number-model]'})
export class NumberModel {
@Input('inputAlias') model: number;
@Output('outputAlias') modelChanged: EventEmitter<number>;
}
interface Person {
name: string;
age: number
}
@Component({template: '<div *ngFor="~{for-empty}"></div>'})
export class ForOfEmpty {}
@Component({template: '<div *ngFor="let ~{for-let-empty}"></div>'})
export class ForOfLetEmpty {}
@Component({template: '<div *ngFor="let i = ~{for-let-i-equal}"></div>'})
export class ForLetIEqual {}
@Component({template: '<div *ngFor="~{for-let}let ~{for-person}person ~{for-of}of ~{for-people}people"> <span>Name: {{~{for-interp-person}person.~{for-interp-name}name}}</span><span>Age: {{person.~{for-interp-age}age}}</span></div>'})
export class ForUsingComponent {
people: Person[];
}
@Component({template: '<div #div> <test-comp #test1> {{~{test-comp-content}}} {{test1.~{test-comp-after-test}name}} {{div.~{test-comp-after-div}.innerText}} </test-comp> </div> <test-comp #test2></test-comp>'})
export class References {}
~{start-test-comp}@Component({selector: 'test-comp', template: '<div>Testing: {{name}}</div>'})
export class TestComponent {
«@Input('ᐱtcNameᐱ') name = 'test';»
«@Output('ᐱtestᐱ') testEvent = new EventEmitter();»
}~{end-test-comp}
@Component({templateUrl: 'test.ng'})
export class TemplateReference {
title = 'Some title';
hero: Hero = {
id: 1,
name: 'Windstorm'
};
anyValue: any;
myClick(event: any) {
}
}
@Component({template: '{{~{empty-interpolation}}}'})
export class EmptyInterpolation {
title = 'Some title';
subTitle = 'Some sub title';
}
`,
'expression-cases.ts': `
import {Component} from '@angular/core';
export interface Person {
name: string;
age: number;
}
@Component({template: '{{~{foo}foo~{foo-end}}}'})
export class WrongFieldReference {
bar = 'bar';
}
@Component({template: '{{~{nam}person.nam~{nam-end}}}'})
export class WrongSubFieldReference {
person: Person = { name: 'Bob', age: 23 };
}
@Component({template: '{{~{myField}myField~{myField-end}}}'})
export class PrivateReference {
private myField = 'My Field';
}
@Component({template: '{{~{mod}"a" ~{mod-end}% 2}}'})
export class ExpectNumericType {}
@Component({template: '{{ (name | lowercase).~{string-pipe}substring }}'})
export class LowercasePipe {
name: string;
}
`,
'ng-for-cases.ts': `
import {Component} from '@angular/core';
export interface Person {
name: string;
age: number;
}
@Component({template: '<div *ngFor="let person of ~{people_1}people_1~{people_1-end}"> <span>{{person.name}}</span> </div>'})
export class UnknownPeople {}
@Component({template: '<div ~{even_1}*ngFor="let person of people; let e = even_1"~{even_1-end}><span>{{person.name}}</span> </div>'})
export class UnknownEven {
people: Person[];
}
@Component({template: '<div *ngFor="let person of people; trackBy ~{trackBy_1}trackBy_1~{trackBy_1-end}"><span>{{person.name}}</span> </div>'})
export class UnknownTrackBy {
people: Person[];
}
`,
'ng-if-cases.ts': `
import {Component} from '@angular/core';
@Component({template: '<div ~{implicit}*ngIf="show; let l=unknown"~{implicit-end}>Showing now!</div>'})
export class ShowIf {
show = false;
}
`,
'test.ng': `~{empty}
<~{start-tag}h~{start-tag-after-h}1~{start-tag-h1} ~{h1-after-space}>~{h1-content} {{~{sub-start}title~{sub-end}}}</h1>
~{after-h1}<h2>{{~{h2-hero}hero.~{h2-name}name}} details!</h2>
<div><label>id: </label>{{~{label-hero}hero.~{label-id}id}}</div>
<div ~{div-attributes}>
<label>name: </label>
</div>
&~{entity-amp}amp;
`,
'test.css': `
body, html {
width: 100%;
}
`,
}
};

View File

@ -14,12 +14,6 @@ import * as ts from 'typescript';
import {Span} from '../src/types';
export type MockData = string | MockDirectory;
export type MockDirectory = {
[name: string]: MockData | undefined;
};
const angularts = /@angular\/(\w|\/|-)+\.tsx?$/;
const rxjsts = /rxjs\/(\w|\/)+\.tsx?$/;
const rxjsmetadata = /rxjs\/(\w|\/)+\.metadata\.json?$/;
@ -41,29 +35,6 @@ const missingCache = new Set<string>([
'/node_modules/@angular/core/src/reflection/platform_reflection_capabilities.metadata.json',
'/node_modules/@angular/forms/src/directives/form_interface.metadata.json',
]);
const cacheUsed = new Set<string>();
const reportedMissing = new Set<string>();
/**
* The cache is valid if all the returned entries are empty.
*/
export function validateCache(): {exists: string[], unused: string[], reported: string[]} {
const exists: string[] = [];
const unused: string[] = [];
for (const fileName of missingCache) {
if (fs.existsSync(fileName)) {
exists.push(fileName);
}
if (!cacheUsed.has(fileName)) {
unused.push(fileName);
}
}
return {
exists,
unused,
reported: Array.from(reportedMissing),
};
}
function isFile(path: string) {
return fs.statSync(path).isFile();
@ -121,7 +92,7 @@ export class MockTypescriptHost implements ts.LanguageServiceHost {
private readonly fileCache = new Map<string, string|undefined>();
constructor(
private readonly scriptNames: string[], _: MockData,
private readonly scriptNames: string[],
private readonly node_modules: string = 'node_modules',
private readonly myPath: typeof path = path) {
const support = setup();
@ -222,6 +193,14 @@ export class MockTypescriptHost implements ts.LanguageServiceHost {
if (content) return removeReferenceMarkers(removeLocationMarkers(content));
}
/**
* Reset the project to its original state, effectively removing all overrides.
*/
reset() {
this.overrides.clear();
this.overrideDirectory.clear();
}
private getRawFileContent(fileName: string): string|undefined {
if (this.overrides.has(fileName)) {
return this.overrides.get(fileName);
@ -232,7 +211,6 @@ export class MockTypescriptHost implements ts.LanguageServiceHost {
return fs.readFileSync(this.myPath.join(path.dirname(libPath), basename), 'utf8');
}
if (missingCache.has(fileName)) {
cacheUsed.add(fileName);
return undefined;
}
@ -250,8 +228,6 @@ export class MockTypescriptHost implements ts.LanguageServiceHost {
return content;
} else {
missingCache.add(fileName);
reportedMissing.add(fileName);
cacheUsed.add(fileName);
}
}
}

View File

@ -9,11 +9,10 @@
import 'reflect-metadata';
import * as ts from 'typescript';
import {create} from '../src/ts_plugin';
import {toh} from './test_data';
import {MockTypescriptHost} from './test_utils';
describe('plugin', () => {
const mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts'], toh);
const mockHost = new MockTypescriptHost(['/app/main.ts', '/app/parsing-cases.ts']);
const service = ts.createLanguageService(mockHost);
const program = service.getProgram();
const plugin = createPlugin(service, mockHost);

View File

@ -11,13 +11,12 @@ import * as ts from 'typescript';
import {TypeScriptServiceHost} from '../src/typescript_host';
import {toh} from './test_data';
import {MockTypescriptHost, findDirectiveMetadataByName} from './test_utils';
describe('TypeScriptServiceHost', () => {
it('should be able to create a typescript host and analyze modules', () => {
const tsLSHost = new MockTypescriptHost(['/app/main.ts'], toh);
const tsLSHost = new MockTypescriptHost(['/app/main.ts']);
const tsLS = ts.createLanguageService(tsLSHost);
const ngLSHost = new TypeScriptServiceHost(tsLSHost, tsLS);
const analyzedModules = ngLSHost.getAnalyzedModules();
@ -34,7 +33,7 @@ describe('TypeScriptServiceHost', () => {
});
it('should be able to analyze modules without a tsconfig.json file', () => {
const tsLSHost = new MockTypescriptHost(['foo.ts'], toh);
const tsLSHost = new MockTypescriptHost(['foo.ts']);
const tsLS = ts.createLanguageService(tsLSHost);
const ngLSHost = new TypeScriptServiceHost(tsLSHost, tsLS);
const analyzedModules = ngLSHost.getAnalyzedModules();
@ -45,7 +44,7 @@ describe('TypeScriptServiceHost', () => {
});
it('should not throw if there is no script names', () => {
const tsLSHost = new MockTypescriptHost([], toh);
const tsLSHost = new MockTypescriptHost([]);
const tsLS = ts.createLanguageService(tsLSHost);
const ngLSHost = new TypeScriptServiceHost(tsLSHost, tsLS);
const analyzedModules = ngLSHost.getAnalyzedModules();
@ -57,7 +56,7 @@ describe('TypeScriptServiceHost', () => {
it('should clear the caches if program changes', () => {
// First create a TypescriptHost with empty script names
const tsLSHost = new MockTypescriptHost([], toh);
const tsLSHost = new MockTypescriptHost([]);
const tsLS = ts.createLanguageService(tsLSHost);
const ngLSHost = new TypeScriptServiceHost(tsLSHost, tsLS);
expect(ngLSHost.getAnalyzedModules().ngModules).toEqual([]);
@ -71,7 +70,7 @@ describe('TypeScriptServiceHost', () => {
});
it('should throw if getSourceFile is called on non-TS file', () => {
const tsLSHost = new MockTypescriptHost([], toh);
const tsLSHost = new MockTypescriptHost([]);
const tsLS = ts.createLanguageService(tsLSHost);
const ngLSHost = new TypeScriptServiceHost(tsLSHost, tsLS);
expect(() => {
@ -80,7 +79,7 @@ describe('TypeScriptServiceHost', () => {
});
it('should be able to find a single inline template', () => {
const tsLSHost = new MockTypescriptHost(['/app/app.component.ts'], toh);
const tsLSHost = new MockTypescriptHost(['/app/app.component.ts']);
const tsLS = ts.createLanguageService(tsLSHost);
const ngLSHost = new TypeScriptServiceHost(tsLSHost, tsLS);
const templates = ngLSHost.getTemplates('/app/app.component.ts');
@ -90,7 +89,7 @@ describe('TypeScriptServiceHost', () => {
});
it('should be able to find multiple inline templates', () => {
const tsLSHost = new MockTypescriptHost(['/app/parsing-cases.ts'], toh);
const tsLSHost = new MockTypescriptHost(['/app/parsing-cases.ts']);
const tsLS = ts.createLanguageService(tsLSHost);
const ngLSHost = new TypeScriptServiceHost(tsLSHost, tsLS);
const templates = ngLSHost.getTemplates('/app/parsing-cases.ts');
@ -98,7 +97,7 @@ describe('TypeScriptServiceHost', () => {
});
it('should be able to find external template', () => {
const tsLSHost = new MockTypescriptHost(['/app/main.ts'], toh);
const tsLSHost = new MockTypescriptHost(['/app/main.ts']);
const tsLS = ts.createLanguageService(tsLSHost);
const ngLSHost = new TypeScriptServiceHost(tsLSHost, tsLS);
ngLSHost.getAnalyzedModules();
@ -110,7 +109,7 @@ describe('TypeScriptServiceHost', () => {
// https://github.com/angular/angular/issues/32301
it('should clear caches when program changes', () => {
const tsLSHost = new MockTypescriptHost(['/app/main.ts'], toh);
const tsLSHost = new MockTypescriptHost(['/app/main.ts']);
const tsLS = ts.createLanguageService(tsLSHost);
const ngLSHost = new TypeScriptServiceHost(tsLSHost, tsLS);
const fileName = '/app/app.component.ts';
@ -162,7 +161,7 @@ describe('TypeScriptServiceHost', () => {
});
it('should not clear caches when external template changes', () => {
const tsLSHost = new MockTypescriptHost(['/app/main.ts'], toh);
const tsLSHost = new MockTypescriptHost(['/app/main.ts']);
const tsLS = ts.createLanguageService(tsLSHost);
const ngLSHost = new TypeScriptServiceHost(tsLSHost, tsLS);
const oldModules = ngLSHost.getAnalyzedModules();
@ -172,7 +171,7 @@ describe('TypeScriptServiceHost', () => {
});
it('should get the correct StaticSymbol for a Directive', () => {
const tsLSHost = new MockTypescriptHost(['/app/app.component.ts', '/app/main.ts'], toh);
const tsLSHost = new MockTypescriptHost(['/app/app.component.ts', '/app/main.ts']);
const tsLS = ts.createLanguageService(tsLSHost);
const ngLSHost = new TypeScriptServiceHost(tsLSHost, tsLS);
ngLSHost.getAnalyzedModules(); // modules are analyzed lazily