Skip to content

Commit

Permalink
test(compiler-cli): tests for standalone components/directives/pipes (#…
Browse files Browse the repository at this point in the history
…45672)

This commit bundles tests for standalone components that are possible after
previous implementation commits. Most new tests are compliance tests, but
a test is also included to validate that the template type-checking system
can work with standalone components as well.

PR Close #45672
  • Loading branch information
alxhub committed Apr 20, 2022
1 parent d3c0fa3 commit b8d3389
Show file tree
Hide file tree
Showing 13 changed files with 545 additions and 1 deletion.

Large diffs are not rendered by default.

@@ -0,0 +1,75 @@
{
"$schema": "../../../test_case_schema.json",
"cases": [
{
"description": "should properly compile a standalone component",
"inputFiles": [
"component.ts"
],
"expectations": [
{
"failureMessage": "Invalid component definition",
"files": [
"component.js"
]
}
]
},
{
"description": "should properly compile a standalone directive",
"inputFiles": [
"directive.ts"
],
"expectations": [
{
"failureMessage": "Invalid directive definition",
"files": [
"directive.js"
]
}
]
},
{
"description": "should properly compile a standalone pipe",
"inputFiles": [
"pipe.ts"
],
"expectations": [
{
"failureMessage": "Invalid pipe definition",
"files": [
"pipe.js"
]
}
]
},
{
"description": "should generate dependencies array from imports",
"inputFiles": [
"imports.ts"
],
"expectations": [
{
"failureMessage": "Invalid standalone component dependencies",
"files": [
"imports.js"
]
}
]
},
{
"description": "should support recursivity in templates",
"inputFiles": [
"recursive.ts"
],
"expectations": [
{
"failureMessage": "Recursive usage not accounted for",
"files": [
"recursive.js"
]
}
]
}
]
}
@@ -0,0 +1,15 @@
StandaloneCmp.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({
type: StandaloneCmp,
selectors: [["ng-component"]],
standalone: true,
features: [i0.ɵɵStandaloneFeature],
decls: 1,
vars: 0,
template: function StandaloneCmp_Template(rf, ctx) {
if (rf & 1) {
i0.ɵɵelement(0, "other-cmp");
}
},
dependencies: [OtherCmp],
encapsulation: 2
});
@@ -0,0 +1,17 @@
import {Component} from '@angular/core';

@Component({
standalone: true,
selector: 'other-cmp',
template: '',
})
export class OtherCmp {
}

@Component({
standalone: true,
template: '<other-cmp></other-cmp>',
imports: [OtherCmp],
})
export class StandaloneCmp {
}
@@ -0,0 +1,4 @@
StandaloneDir.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({
type: StandaloneDir,
standalone: true
});
@@ -0,0 +1,7 @@
import {Directive} from '@angular/core';

@Directive({
standalone: true,
})
export class StandaloneDir {
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

@@ -0,0 +1,69 @@
import {Component, Directive, NgModule, Pipe} from '@angular/core';

@Directive({selector: '[not-standalone]'})
export class NotStandaloneDir {
}

@Pipe({name: 'nspipe'})
export class NotStandalonePipe {
transform(value: any): any {}
}

@NgModule({
declarations: [NotStandaloneDir, NotStandalonePipe],
exports: [NotStandaloneDir, NotStandalonePipe],
})
export class NotStandaloneStuffModule {
}

@Directive({
standalone: true,
selector: '[indirect]',
})
export class IndirectDir {
}

@Pipe({
standalone: true,
name: 'indirectpipe',
})
export class IndirectPipe {
transform(value: any): any {}
}

@NgModule({
imports: [IndirectDir, IndirectPipe],
exports: [NotStandaloneStuffModule, IndirectDir, IndirectPipe],
})
export class SomeModule {
}


@Directive({
standalone: true,
selector: '[direct]',
})
export class DirectDir {
}

@Pipe({
standalone: true,
name: 'directpipe',
})
export class DirectPipe {
transform(value: any): any {}
}

@Component({
standalone: true,
selector: 'test-cmp',
template: `
<p>Reference some non-standalone things:<span not-standalone>{{data | nspipe}}</span></p>
<p>Reference some indirect standalone things:<span indirect>{{data | indirectpipe}}</span></p>
<p>Reference some standalone things directly:<span direct>{{data | directpipe}}</span></p>
`,
imports: [SomeModule, DirectDir, DirectPipe],
})
export class TestCmp {
data = true;
}
@@ -0,0 +1,6 @@
StandalonePipe.ɵpipe = /*@__PURE__*/ i0.ɵɵdefinePipe({
name: "stpipe",
type: StandalonePipe,
pure: true,
standalone: true
});
@@ -0,0 +1,9 @@
import {Pipe} from '@angular/core';

@Pipe({
standalone: true,
name: 'stpipe',
})
export class StandalonePipe {
transform(value: any): any {}
}
@@ -0,0 +1 @@
dependencies: [RecursiveComponent],
@@ -0,0 +1,10 @@
import {Component} from '@angular/core';

@Component({
standalone: true,
selector: 'recursive-cmp',
// Simple recursion. Note: no `imports`.
template: '<recursive-cmp></recursive-cmp>',
})
export class RecursiveComponent {
}
44 changes: 43 additions & 1 deletion packages/compiler-cli/test/ngtsc/standalone_spec.ts
Expand Up @@ -22,7 +22,7 @@ runInEachFileSystem(() => {

beforeEach(() => {
env = NgtscTestEnvironment.setup(testFiles);
env.tsconfig();
env.tsconfig({strictTemplates: true});
});

describe('component-side', () => {
Expand Down Expand Up @@ -264,6 +264,48 @@ runInEachFileSystem(() => {
.toEqual(
`It's declared in the NgModule 'TestModule', but is not exported. Consider exporting it.`);
});

it('should type-check standalone component templates', () => {
env.write('test.ts', `
import {Component, Input, NgModule} from '@angular/core';
@Component({
selector: 'not-standalone',
template: '',
})
export class NotStandaloneCmp {
@Input() value!: string;
}
@NgModule({
declarations: [NotStandaloneCmp],
exports: [NotStandaloneCmp],
})
export class NotStandaloneModule {}
@Component({
standalone: true,
selector: 'is-standalone',
template: '',
})
export class IsStandaloneCmp {
@Input() value!: string;
}
@Component({
standalone: true,
selector: 'test-cmp',
imports: [NotStandaloneModule, IsStandaloneCmp],
template: '<not-standalone [value]="3"></not-standalone><is-standalone [value]="true"></is-standalone>',
})
export class TestCmp {}
`);

const diags = env.driveDiagnostics().map(diag => diag.messageText);
expect(diags.length).toBe(2);
expect(diags).toContain(`Type 'number' is not assignable to type 'string'.`);
expect(diags).toContain(`Type 'boolean' is not assignable to type 'string'.`);
});
});

describe('NgModule-side', () => {
Expand Down

0 comments on commit b8d3389

Please sign in to comment.