test(compiler): add expression absolute span tests for TemplateAsts (#33253)

Previously, we had tested that expressions parsed in a Render3 AST
had correctly-defined absolute spans (spans relative to the entire
template, not the local expression). Sometimes we use Template ASTs
rather than Render3 ASTs, and it's desirable to test for correct
expression spans in the template parser as well.

Adding these tests resolved one bug, similar to the one fixed in
fd4fed14d8, where expressions in the value
of a template attribute were not given an absolute span corresponding to
the start of the attribute name rather than the start of the attribute
value.

The diff on this commit is large, partially because it involves some
structural changes of the template parser testing layout. In particular,
the following is done:

1. Move `createMeta*`-like functions from `template_parser_spec.ts` to
   be exported from a new test utility file.
2. Create an `ExpressionSourceHumanizer`, similar to the one created in
   b04488d692, to allow convenient testing
   of expressions' locations.
3. Create `template_parser_absolute_span_spec.ts`, testing the spans of
   expressions parsed by the template parser. This is very similar to
   the `r3_ast_absolute_span_spec`.

PR Close #33253
This commit is contained in:
ayazhafiz
2019-10-18 09:51:20 -05:00
committed by Andrew Kushnir
parent 2805af900f
commit 3d11355fec
5 changed files with 589 additions and 92 deletions

View File

@ -5,24 +5,24 @@
* 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 {CompileQueryMetadata, CompilerConfig, ProxyClass, StaticSymbol, preserveWhitespacesDefault} from '@angular/compiler';
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeMetadata, CompilePipeSummary, CompileProviderMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, tokenReference} from '@angular/compiler/src/compile_metadata';
import {preserveWhitespacesDefault} from '@angular/compiler';
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeMetadata, CompilePipeSummary, CompileProviderMetadata, CompileTemplateMetadata, CompileTokenMetadata, tokenReference} from '@angular/compiler/src/compile_metadata';
import {DomElementSchemaRegistry} from '@angular/compiler/src/schema/dom_element_schema_registry';
import {ElementSchemaRegistry} from '@angular/compiler/src/schema/element_schema_registry';
import {AttrAst, BoundDirectivePropertyAst, BoundElementPropertyAst, BoundEventAst, BoundTextAst, DirectiveAst, ElementAst, EmbeddedTemplateAst, NgContentAst, PropertyBindingType, ProviderAstType, ReferenceAst, TemplateAst, TemplateAstVisitor, TextAst, VariableAst, templateVisitAll} from '@angular/compiler/src/template_parser/template_ast';
import {TemplateParser, splitClasses} from '@angular/compiler/src/template_parser/template_parser';
import {ChangeDetectionStrategy, ComponentFactory, RendererType2, SchemaMetadata, SecurityContext, ViewEncapsulation} from '@angular/core';
import {SchemaMetadata, SecurityContext} from '@angular/core';
import {Console} from '@angular/core/src/console';
import {TestBed, inject} from '@angular/core/testing';
import {JitReflector} from '@angular/platform-browser-dynamic/src/compiler_reflector';
import {CompileEntryComponentMetadata, CompileStylesheetMetadata} from '../../src/compile_metadata';
import {Identifiers, createTokenForExternalReference, createTokenForReference} from '../../src/identifiers';
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from '../../src/ml_parser/interpolation_config';
import {newArray, noUndefined} from '../../src/util';
import {newArray} from '../../src/util';
import {MockSchemaRegistry} from '../../testing';
import {unparse} from '../expression_parser/utils/unparser';
import {TEST_COMPILER_PROVIDERS} from '../test_bindings';
import {compileDirectiveMetadataCreate, compileTemplateMetadata, createTypeMeta} from './util/metadata';
const someModuleUrl = 'package:someModule';
@ -33,88 +33,6 @@ const MOCK_SCHEMA_REGISTRY = [{
['onEvent'], ['onEvent']),
}];
function createTypeMeta({reference, diDeps}: {reference: any, diDeps?: any[]}):
CompileTypeMetadata {
return {reference: reference, diDeps: diDeps || [], lifecycleHooks: []};
}
function compileDirectiveMetadataCreate(
{isHost, type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
providers, viewProviders, queries, guards, viewQueries, entryComponents, template,
componentViewType, rendererType}: {
isHost?: boolean,
type?: CompileTypeMetadata,
isComponent?: boolean,
selector?: string | null,
exportAs?: string | null,
changeDetection?: ChangeDetectionStrategy | null,
inputs?: string[],
outputs?: string[],
host?: {[key: string]: string},
providers?: CompileProviderMetadata[] | null,
viewProviders?: CompileProviderMetadata[] | null,
queries?: CompileQueryMetadata[] | null,
guards?: {[key: string]: any},
viewQueries?: CompileQueryMetadata[],
entryComponents?: CompileEntryComponentMetadata[],
template?: CompileTemplateMetadata,
componentViewType?: StaticSymbol | ProxyClass | null,
rendererType?: StaticSymbol | RendererType2 | null,
}) {
return CompileDirectiveMetadata.create({
isHost: !!isHost,
type: noUndefined(type) !,
isComponent: !!isComponent,
selector: noUndefined(selector),
exportAs: noUndefined(exportAs),
changeDetection: null,
inputs: inputs || [],
outputs: outputs || [],
host: host || {},
providers: providers || [],
viewProviders: viewProviders || [],
queries: queries || [],
guards: guards || {},
viewQueries: viewQueries || [],
entryComponents: entryComponents || [],
template: noUndefined(template) !,
componentViewType: noUndefined(componentViewType),
rendererType: noUndefined(rendererType),
componentFactory: null,
});
}
function compileTemplateMetadata({encapsulation, template, templateUrl, styles, styleUrls,
externalStylesheets, animations, ngContentSelectors,
interpolation, isInline, preserveWhitespaces}: {
encapsulation?: ViewEncapsulation | null,
template?: string | null,
templateUrl?: string | null,
styles?: string[],
styleUrls?: string[],
externalStylesheets?: CompileStylesheetMetadata[],
ngContentSelectors?: string[],
animations?: any[],
interpolation?: [string, string] | null,
isInline?: boolean,
preserveWhitespaces?: boolean | null,
}): CompileTemplateMetadata {
return new CompileTemplateMetadata({
encapsulation: noUndefined(encapsulation),
template: noUndefined(template),
templateUrl: noUndefined(templateUrl),
htmlAst: null,
styles: styles || [],
styleUrls: styleUrls || [],
externalStylesheets: externalStylesheets || [],
animations: animations || [],
ngContentSelectors: ngContentSelectors || [],
interpolation: noUndefined(interpolation),
isInline: !!isInline,
preserveWhitespaces: preserveWhitespacesDefault(noUndefined(preserveWhitespaces)),
});
}
function humanizeTplAst(
templateAsts: TemplateAst[], interpolationConfig?: InterpolationConfig): any[] {
@ -1136,9 +1054,10 @@ Binding to attribute 'onEvent' is disallowed for security reasons ("<my-componen
}
function createDir(
selector: string, {providers = null, viewProviders = null, deps = [], queries = []}: {
providers?: CompileProviderMetadata[] | null,
viewProviders?: CompileProviderMetadata[] | null,
selector: string,
{providers = undefined, viewProviders = undefined, deps = [], queries = []}: {
providers?: CompileProviderMetadata[] | undefined,
viewProviders?: CompileProviderMetadata[] | undefined,
deps?: string[],
queries?: string[]
} = {}): CompileDirectiveSummary {