Skip to content

Commit d006aa3

Browse files
crisbetothePunderWoman
authored andcommitted
refactor(compiler-cli): add tests for model inputs (angular#54252)
Adds tests in the compiler to verify the compiled output and template type checking behavior of model inputs. PR Close angular#54252
1 parent 67b977e commit d006aa3

File tree

9 files changed

+664
-0
lines changed

9 files changed

+664
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/****************************************************************************************************
2+
* PARTIAL FILE: model_directive_definition.js
3+
****************************************************************************************************/
4+
import { Directive, model } from '@angular/core';
5+
import * as i0 from "@angular/core";
6+
export class TestDir {
7+
constructor() {
8+
this.counter = model(0);
9+
this.name = model.required();
10+
}
11+
}
12+
TestDir.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, deps: [], target: i0.ɵɵFactoryTarget.Directive });
13+
TestDir.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "0.0.0-PLACEHOLDER", type: TestDir, isStandalone: true, inputs: { counter: { classPropertyName: "counter", publicName: "counter", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { counter: "counterChange", name: "nameChange" }, ngImport: i0 });
14+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, decorators: [{
15+
type: Directive,
16+
args: [{
17+
standalone: true,
18+
}]
19+
}] });
20+
21+
/****************************************************************************************************
22+
* PARTIAL FILE: model_directive_definition.d.ts
23+
****************************************************************************************************/
24+
import * as i0 from "@angular/core";
25+
export declare class TestDir {
26+
counter: import("@angular/core").ModelSignal<number>;
27+
name: import("@angular/core").ModelSignal<string>;
28+
static ɵfac: i0.ɵɵFactoryDeclaration<TestDir, never>;
29+
static ɵdir: i0.ɵɵDirectiveDeclaration<TestDir, never, never, { "counter": { "alias": "counter"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": true; "isSignal": true; }; }, { "counter": "counterChange"; "name": "nameChange"; }, never, never, true, never>;
30+
}
31+
32+
/****************************************************************************************************
33+
* PARTIAL FILE: model_component_definition.js
34+
****************************************************************************************************/
35+
import { Component, model } from '@angular/core';
36+
import * as i0 from "@angular/core";
37+
export class TestComp {
38+
constructor() {
39+
this.counter = model(0);
40+
this.name = model.required();
41+
}
42+
}
43+
TestComp.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComp, deps: [], target: i0.ɵɵFactoryTarget.Component });
44+
TestComp.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "0.0.0-PLACEHOLDER", type: TestComp, isStandalone: true, selector: "ng-component", inputs: { counter: { classPropertyName: "counter", publicName: "counter", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { counter: "counterChange", name: "nameChange" }, ngImport: i0, template: 'Works', isInline: true });
45+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComp, decorators: [{
46+
type: Component,
47+
args: [{
48+
standalone: true,
49+
template: 'Works',
50+
}]
51+
}] });
52+
53+
/****************************************************************************************************
54+
* PARTIAL FILE: model_component_definition.d.ts
55+
****************************************************************************************************/
56+
import * as i0 from "@angular/core";
57+
export declare class TestComp {
58+
counter: import("@angular/core").ModelSignal<number>;
59+
name: import("@angular/core").ModelSignal<string>;
60+
static ɵfac: i0.ɵɵFactoryDeclaration<TestComp, never>;
61+
static ɵcmp: i0.ɵɵComponentDeclaration<TestComp, "ng-component", never, { "counter": { "alias": "counter"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": true; "isSignal": true; }; }, { "counter": "counterChange"; "name": "nameChange"; }, never, never, true, never>;
62+
}
63+
64+
/****************************************************************************************************
65+
* PARTIAL FILE: mixed_model_types.js
66+
****************************************************************************************************/
67+
import { Directive, EventEmitter, Input, model, Output } from '@angular/core';
68+
import * as i0 from "@angular/core";
69+
export class TestDir {
70+
constructor() {
71+
this.counter = model(0);
72+
this.modelWithAlias = model(false, { alias: 'alias' });
73+
this.decoratorInput = true;
74+
this.decoratorInputWithAlias = true;
75+
this.decoratorOutput = new EventEmitter();
76+
this.decoratorOutputWithAlias = new EventEmitter();
77+
this.decoratorInputTwoWay = true;
78+
this.decoratorInputTwoWayChange = new EventEmitter();
79+
}
80+
}
81+
TestDir.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, deps: [], target: i0.ɵɵFactoryTarget.Directive });
82+
TestDir.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "0.0.0-PLACEHOLDER", type: TestDir, isStandalone: true, inputs: { counter: { classPropertyName: "counter", publicName: "counter", isSignal: true, isRequired: false, transformFunction: null }, modelWithAlias: { classPropertyName: "modelWithAlias", publicName: "alias", isSignal: true, isRequired: false, transformFunction: null }, decoratorInput: { classPropertyName: "decoratorInput", publicName: "decoratorInput", isSignal: false, isRequired: false, transformFunction: null }, decoratorInputWithAlias: { classPropertyName: "decoratorInputWithAlias", publicName: "publicNameDecorator", isSignal: false, isRequired: false, transformFunction: null }, decoratorInputTwoWay: { classPropertyName: "decoratorInputTwoWay", publicName: "decoratorInputTwoWay", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { counter: "counterChange", modelWithAlias: "aliasChange", decoratorOutput: "decoratorOutput", decoratorOutputWithAlias: "aliasDecoratorOutputWithAlias", decoratorInputTwoWayChange: "decoratorInputTwoWayChange" }, ngImport: i0 });
83+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, decorators: [{
84+
type: Directive,
85+
args: [{
86+
standalone: true,
87+
}]
88+
}], propDecorators: { decoratorInput: [{
89+
type: Input
90+
}], decoratorInputWithAlias: [{
91+
type: Input,
92+
args: ['publicNameDecorator']
93+
}], decoratorOutput: [{
94+
type: Output
95+
}], decoratorOutputWithAlias: [{
96+
type: Output,
97+
args: ['aliasDecoratorOutputWithAlias']
98+
}], decoratorInputTwoWay: [{
99+
type: Input
100+
}], decoratorInputTwoWayChange: [{
101+
type: Output
102+
}] } });
103+
104+
/****************************************************************************************************
105+
* PARTIAL FILE: mixed_model_types.d.ts
106+
****************************************************************************************************/
107+
import { EventEmitter } from '@angular/core';
108+
import * as i0 from "@angular/core";
109+
export declare class TestDir {
110+
counter: import("@angular/core").ModelSignal<number>;
111+
modelWithAlias: import("@angular/core").ModelSignal<boolean>;
112+
decoratorInput: boolean;
113+
decoratorInputWithAlias: boolean;
114+
decoratorOutput: EventEmitter<boolean>;
115+
decoratorOutputWithAlias: EventEmitter<boolean>;
116+
decoratorInputTwoWay: boolean;
117+
decoratorInputTwoWayChange: EventEmitter<boolean>;
118+
static ɵfac: i0.ɵɵFactoryDeclaration<TestDir, never>;
119+
static ɵdir: i0.ɵɵDirectiveDeclaration<TestDir, never, never, { "counter": { "alias": "counter"; "required": false; "isSignal": true; }; "modelWithAlias": { "alias": "alias"; "required": false; "isSignal": true; }; "decoratorInput": { "alias": "decoratorInput"; "required": false; }; "decoratorInputWithAlias": { "alias": "publicNameDecorator"; "required": false; }; "decoratorInputTwoWay": { "alias": "decoratorInputTwoWay"; "required": false; }; }, { "counter": "counterChange"; "modelWithAlias": "aliasChange"; "decoratorOutput": "decoratorOutput"; "decoratorOutputWithAlias": "aliasDecoratorOutputWithAlias"; "decoratorInputTwoWayChange": "decoratorInputTwoWayChange"; }, never, never, true, never>;
120+
}
121+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"$schema": "../test_case_schema.json",
3+
"cases": [
4+
{
5+
"description": "should capture input/output pair in a directive definition",
6+
"inputFiles": ["model_directive_definition.ts"],
7+
"expectations": [
8+
{
9+
"files": [
10+
{
11+
"expected": "model_directive_definition.js",
12+
"generated": "model_directive_definition.js"
13+
}
14+
],
15+
"failureMessage": "Incorrect definition"
16+
}
17+
]
18+
},
19+
{
20+
"description": "should capture input/output pair in a component definition",
21+
"inputFiles": ["model_component_definition.ts"],
22+
"expectations": [
23+
{
24+
"files": [
25+
{
26+
"expected": "model_component_definition.js",
27+
"generated": "model_component_definition.js"
28+
}
29+
],
30+
"failureMessage": "Incorrect definition"
31+
}
32+
]
33+
},
34+
{
35+
"description": "should handle a mix of zone and model inputs",
36+
"inputFiles": ["mixed_model_types.ts"],
37+
"expectations": [
38+
{
39+
"files": [
40+
{
41+
"expected": "mixed_model_types.js",
42+
"generated": "mixed_model_types.js"
43+
}
44+
],
45+
"failureMessage": "Incorrect definition"
46+
}
47+
]
48+
}
49+
]
50+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
TestDir.ɵdir = /*@__PURE__*/ $r3$.ɵɵdefineDirective({
2+
3+
inputs: {
4+
counter: [$r3$.ɵɵInputFlags.SignalBased, "counter"],
5+
modelWithAlias: [$r3$.ɵɵInputFlags.SignalBased, "alias", "modelWithAlias"],
6+
decoratorInput: "decoratorInput",
7+
decoratorInputWithAlias: [$r3$.ɵɵInputFlags.None, "publicNameDecorator", "decoratorInputWithAlias"],
8+
decoratorInputTwoWay: "decoratorInputTwoWay"
9+
},
10+
outputs: {
11+
counter: "counterChange",
12+
modelWithAlias: "aliasChange",
13+
decoratorOutput: "decoratorOutput",
14+
decoratorOutputWithAlias: "aliasDecoratorOutputWithAlias",
15+
decoratorInputTwoWayChange: "decoratorInputTwoWayChange"
16+
},
17+
18+
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {Directive, EventEmitter, Input, model, Output} from '@angular/core';
2+
3+
@Directive({
4+
standalone: true,
5+
})
6+
export class TestDir {
7+
counter = model(0);
8+
modelWithAlias = model(false, {alias: 'alias'});
9+
10+
@Input() decoratorInput = true;
11+
@Input('publicNameDecorator') decoratorInputWithAlias = true;
12+
13+
@Output() decoratorOutput = new EventEmitter<boolean>();
14+
@Output('aliasDecoratorOutputWithAlias') decoratorOutputWithAlias = new EventEmitter<boolean>();
15+
16+
@Input() decoratorInputTwoWay = true;
17+
@Output() decoratorInputTwoWayChange = new EventEmitter<boolean>();
18+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
TestComp.ɵcmp = /*@__PURE__*/ $r3$.ɵɵdefineComponent({
2+
3+
inputs: {
4+
counter: [$r3$.ɵɵInputFlags.SignalBased, "counter"],
5+
name: [$r3$.ɵɵInputFlags.SignalBased, "name"]
6+
},
7+
outputs: {
8+
counter: "counterChange",
9+
name: "nameChange"
10+
},
11+
12+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import {Component, model} from '@angular/core';
2+
3+
@Component({
4+
standalone: true,
5+
template: 'Works',
6+
})
7+
export class TestComp {
8+
counter = model(0);
9+
name = model.required<string>();
10+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
TestDir.ɵdir = /*@__PURE__*/ $r3$.ɵɵdefineDirective({
2+
3+
inputs: {
4+
counter: [$r3$.ɵɵInputFlags.SignalBased, "counter"],
5+
name: [$r3$.ɵɵInputFlags.SignalBased, "name"]
6+
},
7+
outputs: {
8+
counter: "counterChange",
9+
name: "nameChange"
10+
},
11+
12+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import {Directive, model} from '@angular/core';
2+
3+
@Directive({
4+
standalone: true,
5+
})
6+
export class TestDir {
7+
counter = model(0);
8+
name = model.required<string>();
9+
}

0 commit comments

Comments
 (0)