test(language-service): Create proper test project (#32653)
Language service uses a canonical "Tour of Heroes" project to test various features, but the files are all contained in test_data.ts which is hard to read and often contains errors that are difficult to catch without proper IDE syntax highlighting. The directory structure is also not clear from first glance. This PR refactors the test project into standalone files in the proper format. Next up: [ ] Update the interface of MockTypeScript to only accept scriptNames. [ ] Remove test_data.ts PR Close #32653
This commit is contained in:

committed by
Andrew Kushnir

parent
2846505dbd
commit
9d8dc793da
34
packages/language-service/test/project/app/app.component.ts
Normal file
34
packages/language-service/test/project/app/app.component.ts
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @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 {Component} 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;
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @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 {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;
|
||||
}
|
58
packages/language-service/test/project/app/main.ts
Normal file
58
packages/language-service/test/project/app/main.ts
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @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 {CommonModule} from '@angular/common';
|
||||
import {NgModule} from '@angular/core';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
|
||||
import {AppComponent} from './app.component';
|
||||
import {ExpectNumericType, LowercasePipe, PrivateReference, WrongFieldReference, WrongSubFieldReference} from './expression-cases';
|
||||
import {UnknownEven, UnknownPeople, UnknownTrackBy} from './ng-for-cases';
|
||||
import {ShowIf} from './ng-if-cases';
|
||||
import {AttributeBinding, CaseIncompleteOpen, CaseMissingClosing, CaseUnknown, EmptyInterpolation, EventBinding, ForLetIEqual, ForOfEmpty, ForOfLetEmpty, ForUsingComponent, NoValueAttribute, NumberModel, Pipes, PropertyBinding, References, StringModel, TemplateReference, TestComponent, TwoWayBinding} from './parsing-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);
|
43
packages/language-service/test/project/app/ng-for-cases.ts
Normal file
43
packages/language-service/test/project/app/ng-for-cases.ts
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @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 {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[];
|
||||
}
|
19
packages/language-service/test/project/app/ng-if-cases.ts
Normal file
19
packages/language-service/test/project/app/ng-if-cases.ts
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @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 {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<div ~{implicit}*ngIf="show; let l=unknown"~{implicit-end}>
|
||||
Showing now!
|
||||
</div>`,
|
||||
})
|
||||
export class ShowIf {
|
||||
show = false;
|
||||
}
|
167
packages/language-service/test/project/app/parsing-cases.ts
Normal file
167
packages/language-service/test/project/app/parsing-cases.ts
Normal file
@ -0,0 +1,167 @@
|
||||
/**
|
||||
* @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 {Component, Directive, EventEmitter, Input, Output} 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 {
|
||||
}
|
||||
|
||||
/*BeginTestComponent*/ @Component({
|
||||
selector: 'test-comp',
|
||||
template: '<div>Testing: {{name}}</div>',
|
||||
})
|
||||
export class TestComponent {
|
||||
@Input('tcName') name = 'test';
|
||||
@Output('test') testEvent = new EventEmitter();
|
||||
} /*EndTestComponent*/
|
||||
|
||||
@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';
|
||||
}
|
3
packages/language-service/test/project/app/test.css
Normal file
3
packages/language-service/test/project/app/test.css
Normal file
@ -0,0 +1,3 @@
|
||||
body, html {
|
||||
width: 100%;
|
||||
}
|
10
packages/language-service/test/project/app/test.ng
Normal file
10
packages/language-service/test/project/app/test.ng
Normal file
@ -0,0 +1,10 @@
|
||||
~{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;
|
Reference in New Issue
Block a user