@@ -803,6 +803,116 @@ describe('IgxGridState - input properties #grid', () => {
803803 expect ( prodIdColumn . colEnd ) . toBe ( 1 ) ;
804804 } ) ;
805805
806+ it ( 'getState should not mutate live sorting expressions (strategy/owner)' , ( ) => {
807+ const fix = TestBed . createComponent ( IgxGridStateComponent ) ;
808+ fix . detectChanges ( ) ;
809+ const grid = fix . componentInstance . grid ;
810+ const state = fix . componentInstance . state ;
811+
812+ const customStrategy = DefaultSortingStrategy . instance ( ) ;
813+ const owner = { } as any ;
814+ grid . sortingExpressions = [
815+ { fieldName : 'ProductID' , dir : SortingDirection . Asc , ignoreCase : false , strategy : customStrategy , owner }
816+ ] ;
817+ fix . detectChanges ( ) ;
818+
819+ expect ( grid . sortingExpressions [ 0 ] . strategy ) . toBe ( customStrategy , 'strategy should be set before getState' ) ;
820+ expect ( grid . sortingExpressions [ 0 ] . owner ) . toBe ( owner , 'owner should be set before getState' ) ;
821+
822+ state . getState ( false , 'sorting' ) ;
823+
824+ expect ( grid . sortingExpressions [ 0 ] . strategy ) . toBe ( customStrategy , 'strategy should not be removed from live expressions after getState' ) ;
825+ expect ( grid . sortingExpressions [ 0 ] . owner ) . toBe ( owner , 'owner should not be removed from live expressions after getState' ) ;
826+ } ) ;
827+
828+ it ( 'getState should not mutate live groupBy expressions (strategy/owner)' , ( ) => {
829+ const fix = TestBed . createComponent ( IgxGridStateComponent ) ;
830+ fix . detectChanges ( ) ;
831+ const grid = fix . componentInstance . grid ;
832+ const state = fix . componentInstance . state ;
833+
834+ const customStrategy = DefaultSortingStrategy . instance ( ) ;
835+ const owner = { } as any ;
836+ grid . groupingExpressions = [
837+ { fieldName : 'ProductID' , dir : SortingDirection . Asc , ignoreCase : false , strategy : customStrategy , owner }
838+ ] ;
839+ fix . detectChanges ( ) ;
840+
841+ expect ( grid . groupingExpressions [ 0 ] . strategy ) . toBe ( customStrategy , 'strategy should be set before getState' ) ;
842+ expect ( grid . groupingExpressions [ 0 ] . owner ) . toBe ( owner , 'owner should be set before getState' ) ;
843+
844+ const serializedState = state . getState ( false , 'groupBy' ) as IGridState ;
845+ const serializedGroupBy = ( serializedState . groupBy ?. expressions ?? [ ] ) as Array < IGroupingExpression & { owner ?: unknown } > ;
846+
847+ expect ( serializedGroupBy . length ) . toBe ( 1 , 'serialized groupBy state should contain the configured expression' ) ;
848+ expect ( serializedGroupBy [ 0 ] . strategy ) . toBeUndefined ( 'strategy should be removed from serialized groupBy expressions' ) ;
849+ expect ( serializedGroupBy [ 0 ] . owner ) . toBeUndefined ( 'owner should be removed from serialized groupBy expressions' ) ;
850+ expect ( grid . groupingExpressions [ 0 ] . strategy ) . toBe ( customStrategy , 'strategy should not be removed from live groupBy expressions after getState' ) ;
851+ expect ( grid . groupingExpressions [ 0 ] . owner ) . toBe ( owner , 'owner should not be removed from live groupBy expressions after getState' ) ;
852+ } ) ;
853+
854+ it ( 'getState should not mutate live filtering expressions (owner)' , ( ) => {
855+ const fix = TestBed . createComponent ( IgxGridStateComponent ) ;
856+ fix . detectChanges ( ) ;
857+ const grid = fix . componentInstance . grid ;
858+ const state = fix . componentInstance . state ;
859+
860+ const filteringTree = new FilteringExpressionsTree ( FilteringLogic . And ) ;
861+ const productFilteringTree = new FilteringExpressionsTree ( FilteringLogic . And , 'ProductName' ) ;
862+ productFilteringTree . filteringOperands . push ( {
863+ condition : IgxBooleanFilteringOperand . instance ( ) . condition ( 'true' ) ,
864+ conditionName : 'true' ,
865+ fieldName : 'InStock' ,
866+ ignoreCase : true
867+ } ) ;
868+ ( productFilteringTree as IFilteringExpressionsTree ) . owner = 'nestedOwner' ;
869+ filteringTree . filteringOperands . push ( productFilteringTree ) ;
870+ ( filteringTree as IFilteringExpressionsTree ) . owner = 'rootOwner' ;
871+ grid . filteringExpressionsTree = filteringTree ;
872+ fix . detectChanges ( ) ;
873+
874+ expect ( grid . filteringExpressionsTree . owner ) . toBe ( 'rootOwner' , 'root owner should be set before getState' ) ;
875+ expect ( ( grid . filteringExpressionsTree . filteringOperands [ 0 ] as IFilteringExpressionsTree ) . owner )
876+ . toBe ( 'nestedOwner' , 'nested owner should be set before getState' ) ;
877+
878+ state . getState ( false , 'filtering' ) ;
879+
880+ expect ( grid . filteringExpressionsTree . owner ) . toBe ( 'rootOwner' , 'root owner should not be removed from live filtering tree after getState' ) ;
881+ expect ( ( grid . filteringExpressionsTree . filteringOperands [ 0 ] as IFilteringExpressionsTree ) . owner )
882+ . toBe ( 'nestedOwner' , 'nested owner should not be removed from live filtering operand after getState' ) ;
883+ } ) ;
884+
885+ it ( 'getState should not mutate live advancedFiltering expressions (owner)' , ( ) => {
886+ const fix = TestBed . createComponent ( IgxGridStateComponent ) ;
887+ fix . detectChanges ( ) ;
888+ const grid = fix . componentInstance . grid ;
889+ const state = fix . componentInstance . state ;
890+
891+ const filteringTree = new FilteringExpressionsTree ( FilteringLogic . And ) ;
892+ const productFilteringTree = new FilteringExpressionsTree ( FilteringLogic . And , 'ProductName' ) ;
893+ productFilteringTree . filteringOperands . push ( {
894+ condition : IgxBooleanFilteringOperand . instance ( ) . condition ( 'true' ) ,
895+ conditionName : 'true' ,
896+ fieldName : 'InStock' ,
897+ ignoreCase : true
898+ } ) ;
899+ ( productFilteringTree as IFilteringExpressionsTree ) . owner = 'nestedOwner' ;
900+ filteringTree . filteringOperands . push ( productFilteringTree ) ;
901+ ( filteringTree as IFilteringExpressionsTree ) . owner = 'rootOwner' ;
902+ grid . advancedFilteringExpressionsTree = filteringTree ;
903+ fix . detectChanges ( ) ;
904+
905+ expect ( grid . advancedFilteringExpressionsTree . owner ) . toBe ( 'rootOwner' , 'root owner should be set before getState' ) ;
906+ expect ( ( grid . advancedFilteringExpressionsTree . filteringOperands [ 0 ] as IFilteringExpressionsTree ) . owner )
907+ . toBe ( 'nestedOwner' , 'nested owner should be set before getState' ) ;
908+
909+ state . getState ( false , 'advancedFiltering' ) ;
910+
911+ expect ( grid . advancedFilteringExpressionsTree . owner ) . toBe ( 'rootOwner' , 'root owner should not be removed from live advanced filtering tree after getState' ) ;
912+ expect ( ( grid . advancedFilteringExpressionsTree . filteringOperands [ 0 ] as IFilteringExpressionsTree ) . owner )
913+ . toBe ( 'nestedOwner' , 'nested owner should not be removed from live advanced filtering operand after getState' ) ;
914+ } ) ;
915+
806916 it ( 'should preserve column widths when restoring state with all columns hidden' , ( ) => {
807917 const fix = TestBed . createComponent ( IgxGridStateComponent ) ;
808918 fix . detectChanges ( ) ;
0 commit comments