11import { DocumentDefinitionType , DocumentType } from './document' ;
22import {
33 ChooseItem ,
4+ ForEachGroupItem ,
45 ForEachItem ,
6+ GroupingStrategy ,
57 IfItem ,
68 isExpressionHolder ,
79 MappingTree ,
@@ -25,6 +27,7 @@ describe('mapping.ts', () => {
2527 expect ( isExpressionHolder ( new IfItem ( tree ) ) ) . toBe ( true ) ;
2628 expect ( isExpressionHolder ( new WhenItem ( tree ) ) ) . toBe ( true ) ;
2729 expect ( isExpressionHolder ( new ForEachItem ( tree ) ) ) . toBe ( true ) ;
30+ expect ( isExpressionHolder ( new ForEachGroupItem ( tree ) ) ) . toBe ( true ) ;
2831 expect ( isExpressionHolder ( new ValueSelector ( tree ) ) ) . toBe ( true ) ;
2932 expect ( isExpressionHolder ( new VariableItem ( tree , 'myVar' ) ) ) . toBe ( true ) ;
3033 } ) ;
@@ -137,17 +140,71 @@ describe('mapping.ts', () => {
137140 const item = new ForEachItem ( tree ) ;
138141 item . expression = '/Order/Items/Item' ;
139142
140- // Get contextPath twice
141143 const firstCall = item . contextPath ;
142144 const secondCall = item . contextPath ;
143145
144- // Both calls should return different object instances (not mutated)
145146 expect ( firstCall ) . not . toBe ( secondCall ) ;
146147
147- // But they should have the same values
148- if ( firstCall && secondCall ) {
149- expect ( firstCall . contextPath ) . toEqual ( secondCall . contextPath ) ;
150- }
148+ expect ( firstCall ?. pathSegments ) . toEqual ( secondCall ?. pathSegments ) ;
149+ expect ( firstCall ?. isRelative ) . toBe ( secondCall ?. isRelative ) ;
150+ expect ( firstCall ?. documentReferenceName ) . toBe ( secondCall ?. documentReferenceName ) ;
151+ } ) ;
152+ } ) ;
153+
154+ describe ( 'ForEachGroupItem' , ( ) => {
155+ it ( 'should default to GROUP_BY strategy with empty expressions' , ( ) => {
156+ const item = new ForEachGroupItem ( tree ) ;
157+ expect ( item . groupingStrategy ) . toBe ( GroupingStrategy . GROUP_BY ) ;
158+ expect ( item . groupingExpression ) . toBe ( '' ) ;
159+ expect ( item . expression ) . toBe ( '' ) ;
160+ } ) ;
161+
162+ it ( 'doClone() should copy sortItems' , ( ) => {
163+ const item = new ForEachGroupItem ( tree ) ;
164+ const sort = new SortItem ( ) ;
165+ sort . expression = '@price' ;
166+ sort . order = 'descending' ;
167+ item . sortItems = [ sort ] ;
168+
169+ const cloned = item . clone ( ) ;
170+
171+ expect ( cloned . sortItems ) . toHaveLength ( 1 ) ;
172+ expect ( cloned . sortItems [ 0 ] . expression ) . toBe ( '@price' ) ;
173+ expect ( cloned . sortItems [ 0 ] . order ) . toBe ( 'descending' ) ;
174+ expect ( cloned . sortItems [ 0 ] ) . not . toBe ( sort ) ;
175+ } ) ;
176+
177+ it ( 'clone() should copy expression, groupingStrategy, groupingExpression, and children' , ( ) => {
178+ const item = new ForEachGroupItem ( tree ) ;
179+ item . expression = '/Order/Items/Item' ;
180+ item . groupingStrategy = GroupingStrategy . GROUP_ADJACENT ;
181+ item . groupingExpression = 'Category' ;
182+ const child = new ValueSelector ( item ) ;
183+ child . expression = 'ItemId' ;
184+ item . children = [ child ] ;
185+
186+ const cloned = item . clone ( ) ;
187+
188+ expect ( cloned . expression ) . toBe ( '/Order/Items/Item' ) ;
189+ expect ( cloned . groupingStrategy ) . toBe ( GroupingStrategy . GROUP_ADJACENT ) ;
190+ expect ( cloned . groupingExpression ) . toBe ( 'Category' ) ;
191+ expect ( cloned . children ) . toHaveLength ( 1 ) ;
192+ expect ( ( cloned . children [ 0 ] as ValueSelector ) . expression ) . toBe ( 'ItemId' ) ;
193+ expect ( cloned ) . not . toBe ( item ) ;
194+ } ) ;
195+
196+ it ( 'contextPath getter should not mutate the original PathExpression' , ( ) => {
197+ const item = new ForEachGroupItem ( tree ) ;
198+ item . expression = '/Order/Items/Item' ;
199+
200+ const firstCall = item . contextPath ;
201+ const secondCall = item . contextPath ;
202+
203+ expect ( firstCall ) . not . toBe ( secondCall ) ;
204+
205+ expect ( firstCall ?. pathSegments ) . toEqual ( secondCall ?. pathSegments ) ;
206+ expect ( firstCall ?. isRelative ) . toBe ( secondCall ?. isRelative ) ;
207+ expect ( firstCall ?. documentReferenceName ) . toBe ( secondCall ?. documentReferenceName ) ;
151208 } ) ;
152209 } ) ;
153210
0 commit comments