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 } ) ;
@@ -151,6 +154,63 @@ describe('mapping.ts', () => {
151154 } ) ;
152155 } ) ;
153156
157+ describe ( 'ForEachGroupItem' , ( ) => {
158+ it ( 'should default to GROUP_BY strategy with empty expressions' , ( ) => {
159+ const item = new ForEachGroupItem ( tree ) ;
160+ expect ( item . groupingStrategy ) . toBe ( GroupingStrategy . GROUP_BY ) ;
161+ expect ( item . groupingExpression ) . toBe ( '' ) ;
162+ expect ( item . expression ) . toBe ( '' ) ;
163+ } ) ;
164+
165+ it ( 'doClone() should copy sortItems' , ( ) => {
166+ const item = new ForEachGroupItem ( tree ) ;
167+ const sort = new SortItem ( ) ;
168+ sort . expression = '@price' ;
169+ sort . order = 'descending' ;
170+ item . sortItems = [ sort ] ;
171+
172+ const cloned = item . clone ( ) ;
173+
174+ expect ( cloned . sortItems ) . toHaveLength ( 1 ) ;
175+ expect ( cloned . sortItems [ 0 ] . expression ) . toBe ( '@price' ) ;
176+ expect ( cloned . sortItems [ 0 ] . order ) . toBe ( 'descending' ) ;
177+ expect ( cloned . sortItems [ 0 ] ) . not . toBe ( sort ) ;
178+ } ) ;
179+
180+ it ( 'clone() should copy expression, groupingStrategy, groupingExpression, and children' , ( ) => {
181+ const item = new ForEachGroupItem ( tree ) ;
182+ item . expression = '/Order/Items/Item' ;
183+ item . groupingStrategy = GroupingStrategy . GROUP_ADJACENT ;
184+ item . groupingExpression = 'Category' ;
185+ const child = new ValueSelector ( item ) ;
186+ child . expression = 'ItemId' ;
187+ item . children = [ child ] ;
188+
189+ const cloned = item . clone ( ) ;
190+
191+ expect ( cloned . expression ) . toBe ( '/Order/Items/Item' ) ;
192+ expect ( cloned . groupingStrategy ) . toBe ( GroupingStrategy . GROUP_ADJACENT ) ;
193+ expect ( cloned . groupingExpression ) . toBe ( 'Category' ) ;
194+ expect ( cloned . children ) . toHaveLength ( 1 ) ;
195+ expect ( ( cloned . children [ 0 ] as ValueSelector ) . expression ) . toBe ( 'ItemId' ) ;
196+ expect ( cloned ) . not . toBe ( item ) ;
197+ } ) ;
198+
199+ it ( 'contextPath getter should not mutate the original PathExpression' , ( ) => {
200+ const item = new ForEachGroupItem ( tree ) ;
201+ item . expression = '/Order/Items/Item' ;
202+
203+ const firstCall = item . contextPath ;
204+ const secondCall = item . contextPath ;
205+
206+ expect ( firstCall ) . not . toBe ( secondCall ) ;
207+
208+ if ( firstCall && secondCall ) {
209+ expect ( firstCall . contextPath ) . toEqual ( secondCall . contextPath ) ;
210+ }
211+ } ) ;
212+ } ) ;
213+
154214 describe ( 'ValueSelector' , ( ) => {
155215 it ( 'clone() should copy expression and valueType' , ( ) => {
156216 const item = new ValueSelector ( tree , ValueType . ATTRIBUTE ) ;
0 commit comments