@@ -663,3 +663,132 @@ func TestResolver(t *testing.T) {
663663 assert .Equal (t , summary .ResolvedExpressions , 1 )
664664 assert .Equal (t , "resolved-done" , summary .Results [0 ].Replaced )
665665}
666+
667+ // TestResolveFieldWithEmptyBraces tests the regression where strings.Trim() was
668+ // incorrectly stripping {} from expressions. This affected ternary CEL expressions
669+ // that end with empty maps like: condition ? value : {}
670+ func TestResolveFieldWithEmptyBraces (t * testing.T ) {
671+ tests := []struct {
672+ name string
673+ resource map [string ]interface {}
674+ data map [string ]interface {}
675+ field variable.FieldDescriptor
676+ want ResolutionResult
677+ }{
678+ {
679+ name : "standalone expression ending with empty braces" ,
680+ resource : map [string ]interface {}{
681+ "metadata" : map [string ]interface {}{
682+ "annotations" : "${includeAnnotations ? annotations : {}}" ,
683+ },
684+ },
685+ data : map [string ]interface {}{
686+ "includeAnnotations ? annotations : {}" : map [string ]interface {}{},
687+ },
688+ field : variable.FieldDescriptor {
689+ Path : "metadata.annotations" ,
690+ Expressions : []string {"includeAnnotations ? annotations : {}" },
691+ StandaloneExpression : true ,
692+ },
693+ want : ResolutionResult {
694+ Path : "metadata.annotations" ,
695+ Original : "[includeAnnotations ? annotations : {}]" ,
696+ Resolved : true ,
697+ Replaced : map [string ]interface {}{},
698+ },
699+ },
700+ {
701+ name : "complex expression with has() and empty braces" ,
702+ resource : map [string ]interface {}{
703+ "spec" : map [string ]interface {}{
704+ "config" : "${has(schema.config) && includeConfig ? schema.config : {}}" ,
705+ },
706+ },
707+ data : map [string ]interface {}{
708+ "has(schema.config) && includeConfig ? schema.config : {}" : map [string ]interface {}{
709+ "key" : "value" ,
710+ },
711+ },
712+ field : variable.FieldDescriptor {
713+ Path : "spec.config" ,
714+ Expressions : []string {"has(schema.config) && includeConfig ? schema.config : {}" },
715+ StandaloneExpression : true ,
716+ },
717+ want : ResolutionResult {
718+ Path : "spec.config" ,
719+ Original : "[has(schema.config) && includeConfig ? schema.config : {}]" ,
720+ Resolved : true ,
721+ Replaced : map [string ]interface {}{
722+ "key" : "value" ,
723+ },
724+ },
725+ },
726+ {
727+ name : "expression with empty braces on both sides" ,
728+ resource : map [string ]interface {}{
729+ "data" : map [string ]interface {}{
730+ "field" : "${condition ? {} : {}}" ,
731+ },
732+ },
733+ data : map [string ]interface {}{
734+ "condition ? {} : {}" : map [string ]interface {}{},
735+ },
736+ field : variable.FieldDescriptor {
737+ Path : "data.field" ,
738+ Expressions : []string {"condition ? {} : {}" },
739+ StandaloneExpression : true ,
740+ },
741+ want : ResolutionResult {
742+ Path : "data.field" ,
743+ Original : "[condition ? {} : {}]" ,
744+ Resolved : true ,
745+ Replaced : map [string ]interface {}{},
746+ },
747+ },
748+ {
749+ name : "string template with expression ending in braces" ,
750+ resource : map [string ]interface {}{
751+ "spec" : map [string ]interface {}{
752+ "value" : "prefix-${expr ? value : {}}-suffix" ,
753+ },
754+ },
755+ data : map [string ]interface {}{
756+ "expr ? value : {}" : "resolved" ,
757+ },
758+ field : variable.FieldDescriptor {
759+ Path : "spec.value" ,
760+ Expressions : []string {"expr ? value : {}" },
761+ },
762+ want : ResolutionResult {
763+ Path : "spec.value" ,
764+ Original : "[expr ? value : {}]" ,
765+ Resolved : true ,
766+ Replaced : "prefix-resolved-suffix" ,
767+ },
768+ },
769+ }
770+
771+ for _ , tt := range tests {
772+ t .Run (tt .name , func (t * testing.T ) {
773+ r := NewResolver (tt .resource , tt .data )
774+ got := r .resolveField (tt .field )
775+
776+ assert .Equal (t , tt .want .Path , got .Path )
777+ assert .Equal (t , tt .want .Original , got .Original )
778+ assert .Equal (t , tt .want .Resolved , got .Resolved )
779+ assert .Equal (t , tt .want .Replaced , got .Replaced )
780+
781+ if tt .want .Error != nil {
782+ assert .EqualError (t , got .Error , tt .want .Error .Error ())
783+ } else {
784+ assert .NoError (t , got .Error )
785+ }
786+
787+ if tt .want .Resolved {
788+ value , err := r .getValueFromPath (tt .field .Path )
789+ assert .NoError (t , err )
790+ assert .Equal (t , tt .want .Replaced , value )
791+ }
792+ })
793+ }
794+ }
0 commit comments