From 48ae3a0639ec55894a34d536130b44bd7c50f030 Mon Sep 17 00:00:00 2001 From: Keen Yee Liau Date: Fri, 1 May 2020 15:49:10 -0700 Subject: [PATCH] test(language-service): Add method to override inline template (#36890) This commit adds a method `overrideInlineTemplate` to the `MockTypescriptHost`. This allows us to override an inline template in a Component without changing the TypeScript parts. This methods works in a similar way as `MockTypescriptHost.override()`, which is used for overriding external template. PR Close #36890 --- .../language-service/test/completions_spec.ts | 33 ++++++++++++------- .../language-service/test/project/app/main.ts | 4 --- .../test/project/app/parsing-cases.ts | 27 --------------- packages/language-service/test/test_utils.ts | 13 ++++++++ .../test/typescript_host_spec.ts | 2 +- 5 files changed, 35 insertions(+), 44 deletions(-) diff --git a/packages/language-service/test/completions_spec.ts b/packages/language-service/test/completions_spec.ts index ea44326f69..868ac384ad 100644 --- a/packages/language-service/test/completions_spec.ts +++ b/packages/language-service/test/completions_spec.ts @@ -136,34 +136,43 @@ describe('completions', () => { }); it('should be able to return attribute names with an incomplete attribute', () => { - const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'no-value-attribute'); - const completions = ngLS.getCompletionsAtPosition(PARSING_CASES, marker.start); + mockHost.overrideInlineTemplate(APP_COMPONENT, '

'); + const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'no-value-attribute'); + const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start); expectContain(completions, CompletionKind.HTML_ATTRIBUTE, ['id', 'class', 'dir', 'lang']); }); it('should be able to return attributes of an incomplete element', () => { - const m1 = mockHost.getLocationMarkerFor(PARSING_CASES, 'incomplete-open-lt'); - const c1 = ngLS.getCompletionsAtPosition(PARSING_CASES, m1.start); + mockHost.overrideInlineTemplate(APP_COMPONENT, ` +

+ Some <~{incomplete-open-lt}a~{incomplete-open-a} ~{incomplete-open-attr} text +

`); + + const m1 = mockHost.getLocationMarkerFor(APP_COMPONENT, 'incomplete-open-lt'); + const c1 = ngLS.getCompletionsAtPosition(APP_COMPONENT, m1.start); expectContain(c1, CompletionKind.HTML_ELEMENT, ['a', 'div', 'p', 'span']); - const m2 = mockHost.getLocationMarkerFor(PARSING_CASES, 'incomplete-open-a'); - const c2 = ngLS.getCompletionsAtPosition(PARSING_CASES, m2.start); + const m2 = mockHost.getLocationMarkerFor(APP_COMPONENT, 'incomplete-open-a'); + const c2 = ngLS.getCompletionsAtPosition(APP_COMPONENT, m2.start); expectContain(c2, CompletionKind.HTML_ELEMENT, ['a', 'div', 'p', 'span']); - const m3 = mockHost.getLocationMarkerFor(PARSING_CASES, 'incomplete-open-attr'); - const c3 = ngLS.getCompletionsAtPosition(PARSING_CASES, m3.start); + const m3 = mockHost.getLocationMarkerFor(APP_COMPONENT, 'incomplete-open-attr'); + const c3 = ngLS.getCompletionsAtPosition(APP_COMPONENT, m3.start); expectContain(c3, CompletionKind.HTML_ATTRIBUTE, ['id', 'class', 'href', 'name']); }); it('should be able to return completions with a missing closing tag', () => { - const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'missing-closing'); - const completions = ngLS.getCompletionsAtPosition(PARSING_CASES, marker.start); + mockHost.overrideInlineTemplate(APP_COMPONENT, '

Some ~{missing-closing} text

'); + const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'missing-closing'); + const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start); expectContain(completions, CompletionKind.HTML_ELEMENT, ['a', 'div', 'p', 'span', 'h1', 'h2']); }); it('should be able to return common attributes of an unknown tag', () => { - const marker = mockHost.getLocationMarkerFor(PARSING_CASES, 'unknown-element'); - const completions = ngLS.getCompletionsAtPosition(PARSING_CASES, marker.start); + mockHost.overrideInlineTemplate( + APP_COMPONENT, '

Some text

'); + const marker = mockHost.getLocationMarkerFor(APP_COMPONENT, 'unknown-element'); + const completions = ngLS.getCompletionsAtPosition(APP_COMPONENT, marker.start); expectContain(completions, CompletionKind.HTML_ATTRIBUTE, ['id', 'dir', 'lang']); }); diff --git a/packages/language-service/test/project/app/main.ts b/packages/language-service/test/project/app/main.ts index 20b1804528..d79be4001f 100644 --- a/packages/language-service/test/project/app/main.ts +++ b/packages/language-service/test/project/app/main.ts @@ -16,12 +16,8 @@ import * as ParsingCases from './parsing-cases'; imports: [CommonModule, FormsModule], declarations: [ AppComponent, - ParsingCases.CaseIncompleteOpen, - ParsingCases.CaseMissingClosing, - ParsingCases.CaseUnknown, ParsingCases.CounterDirective, ParsingCases.HintModel, - ParsingCases.NoValueAttribute, ParsingCases.NumberModel, ParsingCases.StringModel, ParsingCases.TemplateReference, diff --git a/packages/language-service/test/project/app/parsing-cases.ts b/packages/language-service/test/project/app/parsing-cases.ts index 36a79948a5..65bbbf90c6 100644 --- a/packages/language-service/test/project/app/parsing-cases.ts +++ b/packages/language-service/test/project/app/parsing-cases.ts @@ -10,33 +10,6 @@ import {Component, Directive, EventEmitter, Input, OnChanges, Output, SimpleChan import {Hero} from './app.component'; -@Component({ - template: ` -

- Some <~{incomplete-open-lt}a~{incomplete-open-a} ~{incomplete-open-attr} text -

`, -}) -export class CaseIncompleteOpen { -} - -@Component({ - template: '

Some ~{missing-closing} text

', -}) -export class CaseMissingClosing { -} - -@Component({ - template: '

Some text

', -}) -export class CaseUnknown { -} - -@Component({ - template: '

', -}) -export class NoValueAttribute { -} - @Directive({ selector: '[string-model]', }) diff --git a/packages/language-service/test/test_utils.ts b/packages/language-service/test/test_utils.ts index c58e76ee6f..ffbd45bb61 100644 --- a/packages/language-service/test/test_utils.ts +++ b/packages/language-service/test/test_utils.ts @@ -124,6 +124,19 @@ export class MockTypescriptHost implements ts.LanguageServiceHost { return content; } + /** + * Override the inline template in `fileName`. + * @param fileName path to component that has inline template + * @param content new template + * + * @return the new content of the file + */ + overrideInlineTemplate(fileName: string, content: string): string { + const originalContent = this.getRawFileContent(fileName)!; + const newContent = originalContent.replace(/template: `([\s\S]+)`/, `template: \`${content}\``); + return this.override(fileName, newContent); + } + addScript(fileName: string, content: string) { if (this.scriptVersion.has(fileName)) { throw new Error(`${fileName} is already in the root files.`); diff --git a/packages/language-service/test/typescript_host_spec.ts b/packages/language-service/test/typescript_host_spec.ts index 02978e0736..80682966b8 100644 --- a/packages/language-service/test/typescript_host_spec.ts +++ b/packages/language-service/test/typescript_host_spec.ts @@ -94,7 +94,7 @@ describe('TypeScriptServiceHost', () => { const tsLS = ts.createLanguageService(tsLSHost); const ngLSHost = new TypeScriptServiceHost(tsLSHost, tsLS); const templates = ngLSHost.getTemplates('/app/parsing-cases.ts'); - expect(templates.length).toBe(5); + expect(templates.length).toBe(1); }); it('should be able to find external template', () => {