Skip to content

Commit

Permalink
refactor(compiler-cli): add tests for model inputs (#54252)
Browse files Browse the repository at this point in the history
Adds tests in the compiler to verify the compiled output and template type checking behavior of model inputs.

PR Close #54252
  • Loading branch information
crisbeto authored and thePunderWoman committed Feb 7, 2024
1 parent 67b977e commit d006aa3
Show file tree
Hide file tree
Showing 9 changed files with 664 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/****************************************************************************************************
* PARTIAL FILE: model_directive_definition.js
****************************************************************************************************/
import { Directive, model } from '@angular/core';
import * as i0 from "@angular/core";
export class TestDir {
constructor() {
this.counter = model(0);
this.name = model.required();
}
}
TestDir.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, deps: [], target: i0.ɵɵFactoryTarget.Directive });
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 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, decorators: [{
type: Directive,
args: [{
standalone: true,
}]
}] });

/****************************************************************************************************
* PARTIAL FILE: model_directive_definition.d.ts
****************************************************************************************************/
import * as i0 from "@angular/core";
export declare class TestDir {
counter: import("@angular/core").ModelSignal<number>;
name: import("@angular/core").ModelSignal<string>;
static ɵfac: i0.ɵɵFactoryDeclaration<TestDir, never>;
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>;
}

/****************************************************************************************************
* PARTIAL FILE: model_component_definition.js
****************************************************************************************************/
import { Component, model } from '@angular/core';
import * as i0 from "@angular/core";
export class TestComp {
constructor() {
this.counter = model(0);
this.name = model.required();
}
}
TestComp.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComp, deps: [], target: i0.ɵɵFactoryTarget.Component });
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 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestComp, decorators: [{
type: Component,
args: [{
standalone: true,
template: 'Works',
}]
}] });

/****************************************************************************************************
* PARTIAL FILE: model_component_definition.d.ts
****************************************************************************************************/
import * as i0 from "@angular/core";
export declare class TestComp {
counter: import("@angular/core").ModelSignal<number>;
name: import("@angular/core").ModelSignal<string>;
static ɵfac: i0.ɵɵFactoryDeclaration<TestComp, never>;
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>;
}

/****************************************************************************************************
* PARTIAL FILE: mixed_model_types.js
****************************************************************************************************/
import { Directive, EventEmitter, Input, model, Output } from '@angular/core';
import * as i0 from "@angular/core";
export class TestDir {
constructor() {
this.counter = model(0);
this.modelWithAlias = model(false, { alias: 'alias' });
this.decoratorInput = true;
this.decoratorInputWithAlias = true;
this.decoratorOutput = new EventEmitter();
this.decoratorOutputWithAlias = new EventEmitter();
this.decoratorInputTwoWay = true;
this.decoratorInputTwoWayChange = new EventEmitter();
}
}
TestDir.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, deps: [], target: i0.ɵɵFactoryTarget.Directive });
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 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: TestDir, decorators: [{
type: Directive,
args: [{
standalone: true,
}]
}], propDecorators: { decoratorInput: [{
type: Input
}], decoratorInputWithAlias: [{
type: Input,
args: ['publicNameDecorator']
}], decoratorOutput: [{
type: Output
}], decoratorOutputWithAlias: [{
type: Output,
args: ['aliasDecoratorOutputWithAlias']
}], decoratorInputTwoWay: [{
type: Input
}], decoratorInputTwoWayChange: [{
type: Output
}] } });

/****************************************************************************************************
* PARTIAL FILE: mixed_model_types.d.ts
****************************************************************************************************/
import { EventEmitter } from '@angular/core';
import * as i0 from "@angular/core";
export declare class TestDir {
counter: import("@angular/core").ModelSignal<number>;
modelWithAlias: import("@angular/core").ModelSignal<boolean>;
decoratorInput: boolean;
decoratorInputWithAlias: boolean;
decoratorOutput: EventEmitter<boolean>;
decoratorOutputWithAlias: EventEmitter<boolean>;
decoratorInputTwoWay: boolean;
decoratorInputTwoWayChange: EventEmitter<boolean>;
static ɵfac: i0.ɵɵFactoryDeclaration<TestDir, never>;
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>;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"$schema": "../test_case_schema.json",
"cases": [
{
"description": "should capture input/output pair in a directive definition",
"inputFiles": ["model_directive_definition.ts"],
"expectations": [
{
"files": [
{
"expected": "model_directive_definition.js",
"generated": "model_directive_definition.js"
}
],
"failureMessage": "Incorrect definition"
}
]
},
{
"description": "should capture input/output pair in a component definition",
"inputFiles": ["model_component_definition.ts"],
"expectations": [
{
"files": [
{
"expected": "model_component_definition.js",
"generated": "model_component_definition.js"
}
],
"failureMessage": "Incorrect definition"
}
]
},
{
"description": "should handle a mix of zone and model inputs",
"inputFiles": ["mixed_model_types.ts"],
"expectations": [
{
"files": [
{
"expected": "mixed_model_types.js",
"generated": "mixed_model_types.js"
}
],
"failureMessage": "Incorrect definition"
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
TestDir.ɵdir = /*@__PURE__*/ $r3$.ɵɵdefineDirective({
inputs: {
counter: [$r3$.ɵɵInputFlags.SignalBased, "counter"],
modelWithAlias: [$r3$.ɵɵInputFlags.SignalBased, "alias", "modelWithAlias"],
decoratorInput: "decoratorInput",
decoratorInputWithAlias: [$r3$.ɵɵInputFlags.None, "publicNameDecorator", "decoratorInputWithAlias"],
decoratorInputTwoWay: "decoratorInputTwoWay"
},
outputs: {
counter: "counterChange",
modelWithAlias: "aliasChange",
decoratorOutput: "decoratorOutput",
decoratorOutputWithAlias: "aliasDecoratorOutputWithAlias",
decoratorInputTwoWayChange: "decoratorInputTwoWayChange"
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {Directive, EventEmitter, Input, model, Output} from '@angular/core';

@Directive({
standalone: true,
})
export class TestDir {
counter = model(0);
modelWithAlias = model(false, {alias: 'alias'});

@Input() decoratorInput = true;
@Input('publicNameDecorator') decoratorInputWithAlias = true;

@Output() decoratorOutput = new EventEmitter<boolean>();
@Output('aliasDecoratorOutputWithAlias') decoratorOutputWithAlias = new EventEmitter<boolean>();

@Input() decoratorInputTwoWay = true;
@Output() decoratorInputTwoWayChange = new EventEmitter<boolean>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
TestComp.ɵcmp = /*@__PURE__*/ $r3$.ɵɵdefineComponent({
inputs: {
counter: [$r3$.ɵɵInputFlags.SignalBased, "counter"],
name: [$r3$.ɵɵInputFlags.SignalBased, "name"]
},
outputs: {
counter: "counterChange",
name: "nameChange"
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {Component, model} from '@angular/core';

@Component({
standalone: true,
template: 'Works',
})
export class TestComp {
counter = model(0);
name = model.required<string>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
TestDir.ɵdir = /*@__PURE__*/ $r3$.ɵɵdefineDirective({
inputs: {
counter: [$r3$.ɵɵInputFlags.SignalBased, "counter"],
name: [$r3$.ɵɵInputFlags.SignalBased, "name"]
},
outputs: {
counter: "counterChange",
name: "nameChange"
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {Directive, model} from '@angular/core';

@Directive({
standalone: true,
})
export class TestDir {
counter = model(0);
name = model.required<string>();
}

0 comments on commit d006aa3

Please sign in to comment.