@@ -7833,3 +7833,131 @@ fn test_property_singleton_interpolation_with_sanitizer_angular_v19() {
78337833 assert ! ( js. contains( "ɵɵsanitizeUrl" ) , "Should include ɵɵsanitizeUrl sanitizer. Got:\n {js}" ) ;
78347834 insta:: assert_snapshot!( "property_singleton_interpolation_with_sanitizer_v19" , js) ;
78357835}
7836+
7837+ // ============================================================================
7838+ // Host Directive Alias Tests
7839+ // ============================================================================
7840+
7841+ /// Test host directives with simple aliased inputs/outputs.
7842+ ///
7843+ /// Mirrors the compliance test `host_directives_with_inputs_outputs.ts`.
7844+ /// The mapping array must use `[internalName, publicName]` ordering.
7845+ #[ test]
7846+ fn test_host_directives_with_inputs_outputs ( ) {
7847+ let allocator = Allocator :: default ( ) ;
7848+ let source = r#"
7849+ import { Component, Directive, EventEmitter, Input, Output } from '@angular/core';
7850+
7851+ @Directive({})
7852+ export class HostDir {
7853+ @Input() value = 0;
7854+ @Input() color = '';
7855+ @Output() opened = new EventEmitter();
7856+ @Output() closed = new EventEmitter();
7857+ }
7858+
7859+ @Component({
7860+ selector: 'my-component',
7861+ template: '',
7862+ hostDirectives: [{
7863+ directive: HostDir,
7864+ inputs: ['value', 'color: colorAlias'],
7865+ outputs: ['opened', 'closed: closedAlias'],
7866+ }],
7867+ standalone: false,
7868+ })
7869+ export class MyComponent {
7870+ }
7871+ "# ;
7872+
7873+ let result = transform_angular_file (
7874+ & allocator,
7875+ "test.component.ts" ,
7876+ source,
7877+ & ComponentTransformOptions :: default ( ) ,
7878+ None ,
7879+ ) ;
7880+
7881+ assert ! ( !result. has_errors( ) , "Should not have errors: {:?}" , result. diagnostics) ;
7882+
7883+ let normalized = result. code . replace ( [ ' ' , '\n' , '\t' ] , "" ) ;
7884+
7885+ // Input mappings: 'value' (no alias) → ["value", "value"], 'color: colorAlias' → ["color", "colorAlias"]
7886+ // The array must be [internalName, publicName, ...] i.e. ["value", "value", "color", "colorAlias"]
7887+ assert ! (
7888+ normalized. contains( r#"inputs:["value","value","color","colorAlias"]"# ) ,
7889+ "Input mappings should be [internalName, publicName]. Got:\n {}" ,
7890+ result. code
7891+ ) ;
7892+
7893+ // Output mappings: 'opened' → ["opened", "opened"], 'closed: closedAlias' → ["closed", "closedAlias"]
7894+ assert ! (
7895+ normalized. contains( r#"outputs:["opened","opened","closed","closedAlias"]"# ) ,
7896+ "Output mappings should be [internalName, publicName]. Got:\n {}" ,
7897+ result. code
7898+ ) ;
7899+
7900+ insta:: assert_snapshot!( "host_directives_with_inputs_outputs" , result. code) ;
7901+ }
7902+
7903+ /// Test host directives where the directive has `@Input('alias')` and the host re-aliases.
7904+ ///
7905+ /// Mirrors the compliance test `host_directives_with_host_aliases.ts`.
7906+ #[ test]
7907+ fn test_host_directives_with_host_aliases ( ) {
7908+ let allocator = Allocator :: default ( ) ;
7909+ let source = r#"
7910+ import { Component, Directive, EventEmitter, Input, Output } from '@angular/core';
7911+
7912+ @Directive({})
7913+ export class HostDir {
7914+ @Input('valueAlias') value = 1;
7915+ @Input('colorAlias') color = '';
7916+ @Output('openedAlias') opened = new EventEmitter();
7917+ @Output('closedAlias') closed = new EventEmitter();
7918+ }
7919+
7920+ @Component({
7921+ selector: 'my-component',
7922+ template: '',
7923+ hostDirectives: [{
7924+ directive: HostDir,
7925+ inputs: ['valueAlias', 'colorAlias: customColorAlias'],
7926+ outputs: ['openedAlias', 'closedAlias: customClosedAlias'],
7927+ }],
7928+ standalone: false,
7929+ })
7930+ export class MyComponent {
7931+ }
7932+ "# ;
7933+
7934+ let result = transform_angular_file (
7935+ & allocator,
7936+ "test.component.ts" ,
7937+ source,
7938+ & ComponentTransformOptions :: default ( ) ,
7939+ None ,
7940+ ) ;
7941+
7942+ assert ! ( !result. has_errors( ) , "Should not have errors: {:?}" , result. diagnostics) ;
7943+
7944+ let normalized = result. code . replace ( [ ' ' , '\n' , '\t' ] , "" ) ;
7945+
7946+ // Input mappings: 'valueAlias' → ["valueAlias", "valueAlias"], 'colorAlias: customColorAlias' → ["colorAlias", "customColorAlias"]
7947+ assert ! (
7948+ normalized
7949+ . contains( r#"inputs:["valueAlias","valueAlias","colorAlias","customColorAlias"]"# ) ,
7950+ "Input mappings should be [internalName, publicName]. Got:\n {}" ,
7951+ result. code
7952+ ) ;
7953+
7954+ // Output mappings: 'openedAlias' → ["openedAlias", "openedAlias"], 'closedAlias: customClosedAlias' → ["closedAlias", "customClosedAlias"]
7955+ assert ! (
7956+ normalized
7957+ . contains( r#"outputs:["openedAlias","openedAlias","closedAlias","customClosedAlias"]"# ) ,
7958+ "Output mappings should be [internalName, publicName]. Got:\n {}" ,
7959+ result. code
7960+ ) ;
7961+
7962+ insta:: assert_snapshot!( "host_directives_with_host_aliases" , result. code) ;
7963+ }
0 commit comments