UNPKG

igniteui-angular-sovn

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

910 lines (755 loc) 134 kB
import { Component, DebugElement, ViewChild } from '@angular/core'; import { fakeAsync, TestBed, tick, ComponentFixture, flush } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxGridComponent } from './grid.component'; import { wait, UIInteractions } from '../../test-utils/ui-interactions.spec'; import { GridFunctions, GridSummaryFunctions } from '../../test-utils/grid-functions.spec'; import { configureTestSuite } from '../../test-utils/configure-suite'; import { ProductsComponent, SummaryColumnComponent, FilteringComponent, SummariesGroupByComponent, SummariesGroupByTransactionsComponent } from '../../test-utils/grid-samples.spec'; import { clearGridSubs, setupGridScrollDetection } from '../../test-utils/helper-utils.spec'; import { SampleTestData } from '../../test-utils/sample-test-data.spec'; import { GridSummaryCalculationMode } from '../common/enums'; import { IgxNumberFilteringOperand, IgxStringFilteringOperand } from '../../data-operations/filtering-condition'; import { DropPosition } from '../moving/moving.service'; import { DatePipe } from '@angular/common'; import { IgxGridGroupByRowComponent } from './groupby-row.component'; import { SortingDirection } from '../../data-operations/sorting-strategy'; import { IColumnPipeArgs, IgxColumnComponent, IgxDateSummaryOperand, IgxGridRow, IgxGroupByRow, IgxNumberSummaryOperand, IgxSummaryOperand, IgxSummaryResult, IgxSummaryRow } from '../public_api'; describe('IgxGrid - Summaries #grid', () => { const SUMMARY_CLASS = '.igx-grid-summary'; const ITEM_CLASS = 'igx-grid-summary__item'; const SUMMARY_ROW = 'igx-grid-summary-row'; const SUMMARY_CELL = 'igx-grid-summary-cell'; const EMPTY_SUMMARY_CLASS = 'igx-grid-summary--empty'; const DEBOUNCETIME = 30; configureTestSuite((() => { return TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, CustomSummariesComponent, ProductsComponent, SummaryColumnComponent, FilteringComponent, SummariesGroupByComponent, SummariesGroupByTransactionsComponent ] }); })); describe('Base tests: ', () => { describe('in grid with no summaries defined: ', () => { let fixture: ComponentFixture<ProductsComponent>; let grid: IgxGridComponent; beforeEach(() => { fixture = TestBed.createComponent(ProductsComponent); fixture.detectChanges(); grid = fixture.componentInstance.grid; }); it('should not have summary if no summary is active ', () => { expect(fixture.debugElement.query(By.css(SUMMARY_CLASS))).toBeNull(); }); it('should enableSummaries through grid API ', () => { expect(grid.hasSummarizedColumns).toBe(false); let tFoot = GridFunctions.getGridFooterWrapper(fixture).nativeElement.getBoundingClientRect().height; expect(tFoot < grid.defaultSummaryHeight).toBe(true); grid.enableSummaries([{ fieldName: 'ProductName' }, { fieldName: 'ProductID' }]); fixture.detectChanges(); const summaryRow = GridSummaryFunctions.getRootSummaryRow(fixture); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, [], []); expect(grid.getColumnByName('ProductID').hasSummary).toBe(true); expect(grid.getColumnByName('ProductName').hasSummary).toBe(true); expect(grid.getColumnByName('OrderDate').hasSummary).toBe(false); grid.summaryRowHeight = 0; fixture.detectChanges(); tFoot = GridFunctions.getGridFooterWrapper(fixture).nativeElement.getBoundingClientRect().height; expect(tFoot).toEqual(grid.defaultSummaryHeight); }); it(`should recalculate grid sizes correctly when the column is outside of the viewport`, () => { grid.width = '300px'; fixture.detectChanges(); grid.getColumnByName('UnitsInStock').hasSummary = true; grid.summaryRowHeight = null; fixture.detectChanges(); const tFoot = GridFunctions.getGridFooterWrapper(fixture).nativeElement.getBoundingClientRect().height; expect(tFoot).toEqual(5 * grid.defaultSummaryHeight); expect(GridSummaryFunctions.getRootSummaryRow(fixture)).toBeDefined(); }); it(`Should update summary section when the column is outside of the viewport and have identical width with others`, (async () => { grid.getColumnByName('UnitsInStock').hasSummary = true; grid.width = '300px'; await wait(100); fixture.detectChanges(); grid.addRow({ ProductID: 11, ProductName: 'Belgian Chocolate', InStock: true, UnitsInStock: 99000, OrderDate: new Date('2018-03-01') }); await wait(30); fixture.detectChanges(); grid.dataRowList.first.virtDirRow.scrollTo(3); await wait(30); fixture.detectChanges(); const summaryRow = GridSummaryFunctions.getRootSummaryRow(fixture); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['11', '0', '99,000', '138,004', '12,545.818']); })); it('When we have data which is undefined and enable summary per defined column, error should not be thrown', () => { const idColumn = grid.getColumnByName('ProductID'); expect(grid.data.length > 0).toEqual(true); fixture.componentInstance.data = undefined; fixture.detectChanges(); expect(grid.data).toEqual([]); expect(() => { grid.enableSummaries(idColumn.field); fixture.detectChanges(); }).not.toThrow(); }); }); describe('custom summaries: ', () => { let fixture: ComponentFixture<CustomSummariesComponent>; let grid: IgxGridComponent; beforeEach(() => { fixture = TestBed.createComponent(CustomSummariesComponent); fixture.detectChanges(); grid = fixture.componentInstance.grid1; }); it('should properly render custom summaries', () => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fixture); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Sum', 'Avg'], ['10', '39,004', '3,900.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Earliest', 'Items InStock'], ['May 17, 1990', '1337']); grid.filter('UnitsInStock', '0', IgxNumberFilteringOperand.instance().condition('lessThan'), true); fixture.detectChanges(); const filterResult = grid.rowList.length; expect(filterResult).toEqual(0); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Sum', 'Avg'], ['0', '0', '0']); }); it('should properly calculate all data custom summaries height', () => { grid.getColumnByName('UnitsInStock').summaries = fixture.componentInstance.allDataAvgSummary; grid.getColumnByName('OrderDate').summaries = fixture.componentInstance.allDataAvgSummary; fixture.detectChanges(); const summaryRow = GridSummaryFunctions.getRootSummaryRow(fixture); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Test 1', 'Test 2'], ['10', '50', '150']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Test 3'], ['10', '850']); grid.summaryRowHeight = undefined; fixture.detectChanges(); const tFootHeight = GridFunctions.getGridFooterWrapper(fixture).nativeElement.getBoundingClientRect().height; expect(tFootHeight).toBeGreaterThanOrEqual(3 * grid.defaultSummaryHeight); }); it('should change custom summaries at runtime', () => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fixture); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Sum', 'Avg'], ['10', '39,004', '3,900.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Earliest', 'Items InStock'], ['May 17, 1990', '1337']); GridSummaryFunctions.verifyVisibleSummariesHeight(fixture, 3, grid.defaultSummaryHeight); grid.getColumnByName('UnitsInStock').summaries = fixture.componentInstance.dealsSummaryMinMax; grid.summaryRowHeight = 0; fixture.detectChanges(); const tFootHeight = GridFunctions.getGridFooterWrapper(fixture).nativeElement.getBoundingClientRect().height; expect(tFootHeight).toBe(2 * grid.defaultSummaryHeight); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Min', 'Max'], ['0', '20,000']); GridSummaryFunctions.verifyVisibleSummariesHeight(fixture, 2, grid.defaultSummaryHeight); }); it('should be able to access alldata from each summary', () => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fixture); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Sum', 'Avg'], ['10', '39,004', '3,900.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Earliest', 'Items InStock'], ['May 17, 1990', '1337']); GridSummaryFunctions.verifyVisibleSummariesHeight(fixture, 3, grid.defaultSummaryHeight); grid.getColumnByName('UnitsInStock').summaries = fixture.componentInstance.inStockSummary; fixture.detectChanges(); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Items InStock'], ['10', '0', '20,000', '39,004', '3,900.4', '6']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Earliest', 'Items InStock'], ['May 17, 1990', '1337']); grid.getCellByColumn(4, 'InStock').update(true); fixture.detectChanges(); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Items InStock'], ['10', '0', '20,000', '39,004', '3,900.4', '7']); grid.filter('UnitsInStock', 0, IgxNumberFilteringOperand.instance().condition('equals')); fixture.detectChanges(); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Items InStock'], ['3', '0', '0', '0', '0', '1']); }); it('Last column summary cell should be aligned according to its data cells', () => { grid.columnList.forEach(c => { c.width = '150px'; }); grid.getColumnByName('UnitsInStock').hasSummary = true; grid.width = '900px'; grid.height = '500px'; fixture.detectChanges(); // Get last cell of first data row const lastColumnNormalCell = GridFunctions.getRowCells(fixture, 0)[4]; const lastColumnNormalCellRect = lastColumnNormalCell.nativeElement.getBoundingClientRect(); // Get last summary cell of the summary row const summaryRow = GridSummaryFunctions.getRootSummaryRow(fixture); const lastColumnSummaryCell = GridSummaryFunctions.getSummaryCellByVisibleIndex(summaryRow, 4); const lastColumnSummaryCellRect = lastColumnSummaryCell.nativeElement.getBoundingClientRect(); expect(lastColumnSummaryCellRect.left).toBe(lastColumnNormalCellRect.left, 'summary cell and data cell are not left aligned'); expect(lastColumnSummaryCellRect.right).toBe(lastColumnNormalCellRect.right, 'summary cell and data cell are not right aligned'); }); }); describe('specific data: ', () => { let fixture: ComponentFixture<FilteringComponent>; let grid: IgxGridComponent; beforeEach(() => { fixture = TestBed.createComponent(FilteringComponent); fixture.detectChanges(); grid = fixture.componentInstance.grid; }); it('should have correct summaries when there are null and undefined values', () => { grid.getColumnByName('ProductName').hasSummary = true; grid.getColumnByName('Downloads').hasSummary = true; grid.getColumnByName('Released').hasSummary = true; grid.getColumnByName('ReleaseDate').hasSummary = true; fixture.detectChanges(); const summaryRow = fixture.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['8']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '1', '1,000', '2,204', '275.5']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count'], ['8']); const options: Intl.DateTimeFormatOptions = { year: 'numeric', month: 'short', day: 'numeric' }; const earliest = SampleTestData.timeGenerator.timedelta(SampleTestData.today, 'month', -1).toLocaleString('us', options); const latest = SampleTestData.timeGenerator.timedelta(SampleTestData.today, 'month', 1).toLocaleString('us', options); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['8', earliest, latest]); }); }); describe('', () => { let fix; let grid: IgxGridComponent; beforeEach(() => { fix = TestBed.createComponent(SummaryColumnComponent); fix.detectChanges(); grid = fix.componentInstance.grid; }); it('should disableSummaries through grid API ', () => { const summariedColumns = []; grid.columnList.forEach((col) => { if (col.hasSummary) { summariedColumns.push(col.field); } }); grid.disableSummaries(summariedColumns); fix.detectChanges(); expect(GridSummaryFunctions.getRootSummaryRow(fix)).toBeNull(); expect(grid.hasSummarizedColumns).toBe(false); }); it('should change summary operand through grid API', () => { grid.enableSummaries([{ fieldName: 'UnitsInStock', customSummary: fix.componentInstance.dealsSummaryMinMax }]); grid.summaryRowHeight = 0; fix.detectChanges(); const summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); const tFootHeight = GridFunctions.getGridFooterWrapper(fix).nativeElement.getBoundingClientRect().height; GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Min', 'Max'], ['0', '20,000']); GridSummaryFunctions.verifyVisibleSummariesHeight(fix, 3, grid.defaultSummaryHeight); expect(tFootHeight).toBe(3 * grid.defaultSummaryHeight); }); it('should have summary per each column that \'hasSummary\'= true', () => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], []); }); it('should have count summary for string and boolean data types', () => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); grid.columnList.forEach((col) => { if (col.hasSummary && (col.dataType === 'string' || col.dataType === 'boolean')) { GridSummaryFunctions.verifyColumnSummaries(summaryRow, col.visibleIndex, ['Count'], []); } }); }); it('should have count, min, max, avg and sum summary for numeric data types', () => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); grid.columnList.forEach((col) => { if (col.hasSummary && (col.dataType === 'number')) { GridSummaryFunctions.verifyColumnSummaries(summaryRow, col.visibleIndex, ['Count', 'Min', 'Max', 'Sum', 'Avg'], []); } }); }); it('should have count, earliest and latest summary for \'date\' data types', () => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); grid.columnList.forEach((col) => { if (col.hasSummary && (col.dataType === 'date')) { GridSummaryFunctions.verifyColumnSummaries(summaryRow, col.visibleIndex, ['Count', 'Earliest', 'Latest'], []); } }); }); it('should summary function stay active when is clicked on it\'s label', () => { const summary = fix.debugElement.queryAll(By.css(SUMMARY_CELL))[3]; const min: DebugElement = summary.query(By.css('[title=\'Min\']')); expect(min.parent.nativeElement.classList.contains(ITEM_CLASS)).toBeTruthy(); min.triggerEventHandler('click', null); fix.detectChanges(); expect(min.parent.nativeElement.classList.contains(ITEM_CLASS)).toBeTruthy(); expect(summary.query(By.css('[title=\'Count\']')).parent.nativeElement.classList.contains(ITEM_CLASS)).toBeTruthy(); expect(summary.query(By.css('[title=\'Max\']')).parent.nativeElement.classList.contains(ITEM_CLASS)).toBeTruthy(); expect(summary.query(By.css('[title=\'Sum\']')).parent.nativeElement.classList.contains(ITEM_CLASS)).toBeTruthy(); expect(summary.query(By.css('[title=\'Avg\']')).parent.nativeElement.classList.contains(ITEM_CLASS)).toBeTruthy(); }); it('should calculate summaries for \'number\' dataType or return if no data is provided', () => { const summaryClass = fix.componentInstance.numberSummary; const summaries = summaryClass.operate(fix.componentInstance.data.map((x) => x['UnitsInStock'])); expect(summaries[0].summaryResult).toBe(10); expect(summaries[1].summaryResult).toBe(0); expect(summaries[2].summaryResult).toBe(20000); expect(summaries[3].summaryResult).toBe(39004); expect(summaries[4].summaryResult).toBe(3900.4); const emptySummaries = summaryClass.operate(); expect(emptySummaries[0].summaryResult).toBe(0); expect(typeof emptySummaries[1].summaryResult).not.toEqual(undefined); expect(typeof emptySummaries[2].summaryResult).not.toEqual(undefined); expect(typeof emptySummaries[3].summaryResult).not.toEqual(undefined); expect(typeof emptySummaries[4].summaryResult).not.toEqual(undefined); expect(typeof emptySummaries[1].summaryResult).not.toEqual(null); expect(typeof emptySummaries[2].summaryResult).not.toEqual(null); expect(typeof emptySummaries[3].summaryResult).not.toEqual(null); expect(typeof emptySummaries[4].summaryResult).not.toEqual(null); expect(emptySummaries[1].summaryResult === 0).toBeTruthy(); expect(emptySummaries[2].summaryResult === 0).toBeTruthy(); expect(emptySummaries[3].summaryResult === 0).toBeTruthy(); expect(emptySummaries[4].summaryResult === 0).toBeTruthy(); }); it('should calculate summaries for \'date\' dataType or return if no data is provided', () => { const summaryClass = fix.componentInstance.dateSummary; const pipe = new DatePipe('en-US'); const summaries = summaryClass.operate(fix.componentInstance.data.map((x) => x['OrderDate'])); expect(summaries[0].summaryResult).toBe(10); expect(pipe.transform(summaries[1].summaryResult, 'mediumDate')).toBe('May 17, 1990'); expect(pipe.transform(summaries[2].summaryResult, 'mediumDate')).toBe('Dec 25, 2025'); const emptySummaries = summaryClass.operate([]); expect(emptySummaries[0].summaryResult).toBe(0); expect(emptySummaries[1].summaryResult).toBe(undefined); expect(emptySummaries[2].summaryResult).toBe(undefined); }); it('should display summaries for \'date\' dataType based on column formatter', () => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); const pipe = new DatePipe('fr-FR'); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); grid.getColumnByName('OrderDate').summaryFormatter = ((summaryResult: IgxSummaryResult, summaryOperand: IgxSummaryOperand) => { const result = summaryResult.summaryResult; if (summaryOperand instanceof IgxDateSummaryOperand && summaryResult.key !== 'count' && result !== null && result !== undefined) { return pipe.transform(result, 'mediumDate'); } return result; }); fix.detectChanges(); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', '17 mai 1990', '25 déc. 2025']); }); it('should calc tfoot height according number of summary functions', () => { const summaries = fix.debugElement.queryAll(By.css(SUMMARY_CELL)); const footerRow = GridSummaryFunctions.getRootSummaryRow(fix).nativeElement.getBoundingClientRect().height; const tfootSize = +footerRow; grid.summaryRowHeight = null; fix.detectChanges(); const expectedHeight = GridSummaryFunctions.calcMaxSummaryHeight(grid.columnList, summaries, grid.defaultSummaryHeight); expect(tfootSize).toBe(expectedHeight); }); it('should be able to change \'hasSummary\' property runtime and to recalculate grid sizes correctly', fakeAsync(() => { grid.columnList.forEach((col) => { if (col.field !== 'ProductID') { expect(grid.getColumnByName(col.field).hasSummary).toBe(true); } }); grid.getColumnByName('UnitsInStock').hasSummary = false; grid.summaryRowHeight = 0; tick(100); fix.detectChanges(); expect(grid.getColumnByName('UnitsInStock').hasSummary).toBe(false); const summaries = fix.debugElement.queryAll(By.css(SUMMARY_CELL)).filter((el) => el.nativeElement.classList.contains(EMPTY_SUMMARY_CLASS) === false); const tfootSize = GridSummaryFunctions.getRootSummaryRow(fix).nativeElement.getBoundingClientRect().height; const expectedHeight = GridSummaryFunctions.calcMaxSummaryHeight(grid.columnList, summaries, grid.defaultSummaryHeight); expect(tfootSize).toBe(expectedHeight); grid.getColumnByName('ProductName').hasSummary = false; grid.getColumnByName('InStock').hasSummary = false; grid.getColumnByName('OrderDate').hasSummary = false; fix.detectChanges(); tick(100); expect(GridSummaryFunctions.getRootSummaryRow(fix)).toBeNull(); expect(grid.hasSummarizedColumns).toBe(false); })); it('should render correct data after hiding one bigger and then one smaller summary when scrolled to the bottom', (async () => { grid.data = SampleTestData.foodProductData(); grid.width = '800px'; grid.height = '600px'; grid.allowFiltering = false; fix.detectChanges(); await wait(100); let rowsRendered; let tbody; let expectedRowLenght; let firstCellsText; GridFunctions.scrollTop(grid, 10000); fix.detectChanges(); await wait(100); fix.detectChanges(); rowsRendered = GridFunctions.getRows(fix); tbody = GridFunctions.getGridDisplayContainer(fix).nativeElement.getBoundingClientRect().height; expectedRowLenght = Math.round(parseFloat(tbody) / grid.defaultRowHeight); expect(rowsRendered.length).toEqual(expectedRowLenght); grid.disableSummaries(['ProductName', 'InStock', 'UnitsInStock']); fix.detectChanges(); await wait(100); fix.detectChanges(); rowsRendered = GridFunctions.getRows(fix); tbody = GridFunctions.getGridDisplayContainer(fix).nativeElement.getBoundingClientRect().height; expectedRowLenght = Math.ceil(parseFloat(tbody) / grid.defaultRowHeight) - 1; firstCellsText = rowsRendered.map((item) => { const cellElem = GridFunctions.getRowCells(fix, 0, item)[0]; if (cellElem) { return GridFunctions.getValueFromCellElement(cellElem); } }); expect(rowsRendered.length).toEqual(expectedRowLenght); let expectedFirstCellNum = grid.data.length - expectedRowLenght + 1; for (let i = 0; i < rowsRendered.length - 1; i++) { expect(firstCellsText[i]).toEqual((expectedFirstCellNum + i).toString()); } grid.disableSummaries(['OrderDate']); fix.detectChanges(); await wait(100); fix.detectChanges(); rowsRendered = GridFunctions.getRows(fix); tbody = GridFunctions.getGridDisplayContainer(fix).nativeElement.getBoundingClientRect().height; expectedRowLenght = Math.ceil(parseFloat(tbody) / grid.defaultRowHeight) - 1; firstCellsText = rowsRendered.map((item) => { const cellElem = GridFunctions.getRowCells(fix, 0, item)[0]; if (cellElem) { return GridFunctions.getValueFromCellElement(cellElem); } }); expect(rowsRendered.length).toEqual(expectedRowLenght); expectedFirstCellNum = grid.data.length - expectedRowLenght + 1; for (let i = 0; i < rowsRendered.length - 1; i++) { expect(firstCellsText[i]).toEqual((expectedFirstCellNum + i).toString()); } })); it('should be able to set the height of the summary row through summaryRowHeight input unless the value is falsy', () => { const summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); const summaryRowHeight = 300; grid.summaryRowHeight = summaryRowHeight; fix.detectChanges(); expect(summaryRow.nativeElement.offsetHeight).toBe(summaryRowHeight); grid.summaryRowHeight = 0; fix.detectChanges(); expect(summaryRow.nativeElement.offsetHeight).not.toBeFalsy(); grid.summaryRowHeight = null; fix.detectChanges(); expect(summaryRow.nativeElement.offsetHeight).not.toBeFalsy(); }); it('should display the formatted summary value in the summary cells\' tooltip', () => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); const pipe = new DatePipe('fr-FR'); const summary = GridSummaryFunctions.getSummaryCellByVisibleIndex(summaryRow, 4); const summaryItems = summary.queryAll(By.css('.igx-grid-summary__item')); let summaryResultsValues = ['10', 'May 17, 1990', 'Dec 25, 2025']; for (let i = 0; i < summaryItems.length; i++) { const summaryItem = summaryItems[i]; const summaryResult = summaryItem.query(By.css('.igx-grid-summary__result')); const summaryResultTooltip = summaryResult.nativeElement.getAttribute('title'); expect(summaryResultsValues[i]).toEqual(summaryResultTooltip); } grid.getColumnByName('OrderDate').summaryFormatter = ((summaryResult: IgxSummaryResult, summaryOperand: IgxSummaryOperand) => { const result = summaryResult.summaryResult; if (summaryOperand instanceof IgxDateSummaryOperand && summaryResult.key !== 'count' && result !== null && result !== undefined) { return pipe.transform(result, 'mediumDate'); } return result; }); fix.detectChanges(); summaryResultsValues = ['10', '17 mai 1990', '25 déc. 2025']; for (let i = 0; i < summaryItems.length; i++) { const summaryItem = summaryItems[i]; const summaryResult = summaryItem.query(By.css('.igx-grid-summary__result')); const summaryResultTooltip = summaryResult.nativeElement.getAttribute('title'); expect(summaryResultsValues[i]).toEqual(summaryResultTooltip); } }); }); }); describe('Integration Scenarios: ', () => { describe('', () => { let fix; let grid: IgxGridComponent; beforeEach(() => { fix = TestBed.createComponent(SummaryColumnComponent); fix.detectChanges(); grid = fix.componentInstance.grid; }); it('Filtering: should calculate summaries only over filteredData', fakeAsync(() => { grid.filter('UnitsInStock', 0, IgxNumberFilteringOperand.instance().condition('equals'), true); fix.detectChanges(); let filterResult = grid.rowList.length; expect(filterResult).toEqual(3); let summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['3']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['3']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '0', '0', '0', '0']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['3', 'Jul 27, 2001', 'Oct 11, 2007']); grid.filter('ProductID', 0, IgxNumberFilteringOperand.instance().condition('equals'), true); fix.detectChanges(); filterResult = grid.rowList.length; expect(filterResult).toEqual(0); summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['0']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['0']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['0', '0', '0', '0', '0']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['0', '', '']); grid.clearFilter(); fix.detectChanges(); filterResult = grid.rowList.length; expect(filterResult).toEqual(10); summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); })); it('Moving: should move summaries when move column', fakeAsync(() => { grid.moving = true; const colUnitsInStock = grid.getColumnByName('UnitsInStock'); const colProductID = grid.getColumnByName('ProductID'); fix.detectChanges(); grid.moveColumn(colUnitsInStock, colProductID, DropPosition.BeforeDropTarget); tick(); fix.detectChanges(); const summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); })); it('Hiding: should hide summary row when a column which has summary is hidded', fakeAsync(() => { grid.getColumnByName('ProductName').hasSummary = false; grid.getColumnByName('InStock').hasSummary = false; grid.getColumnByName('OrderDate').hasSummary = false; // grid.recalculateSummaries(); fix.detectChanges(); tick(100); let summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, [], []); grid.getColumnByName('UnitsInStock').hidden = true; tick(); fix.detectChanges(); summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); expect(summaryRow).toBeNull(); expect(grid.hasSummarizedColumns).toBe(false); grid.getColumnByName('UnitsInStock').hidden = false; tick(); fix.detectChanges(); summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); expect(summaryRow).toBeDefined(); expect(grid.hasSummarizedColumns).toBe(true); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, [], []); })); it('Hiding: should recalculate summary area after column with enabled summary is hidden', fakeAsync(() => { grid.summaryRowHeight = undefined; let tFoot = GridFunctions.getGridFooterWrapper(fix).nativeElement.getBoundingClientRect().height; expect(tFoot).toEqual(5 * grid.defaultSummaryHeight); grid.getColumnByName('UnitsInStock').hidden = true; tick(); fix.detectChanges(); tFoot = GridFunctions.getGridFooterWrapper(fix).nativeElement.getBoundingClientRect().height; expect(tFoot).toEqual(3 * grid.defaultSummaryHeight); expect(grid.hasSummarizedColumns).toBe(true); let summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); grid.getColumnByName('UnitsInStock').hidden = false; grid.summaryRowHeight = 0; tick(); fix.detectChanges(); expect(grid.hasSummarizedColumns).toBe(true); tFoot = GridFunctions.getGridFooterWrapper(fix).nativeElement.getBoundingClientRect().height; expect(tFoot).toEqual(5 * grid.defaultSummaryHeight); summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); })); it('CRUD: should recalculate summary functions rowAdded', () => { grid.addRow({ ProductID: 11, ProductName: 'Belgian Chocolate', InStock: true, UnitsInStock: 99000, OrderDate: new Date('2018-03-01') }); fix.detectChanges(); const summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['11']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['11']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['11', '0', '99,000', '138,004', '12,545.818']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['11', 'May 17, 1990', 'Dec 25, 2025']); }); it('CRUD: should recalculate summary functions rowDeleted', () => { grid.deleteRow(9); fix.detectChanges(); const summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['9']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['9']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['9', '0', '20,000', '32,006', '3,556.222']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['9', 'May 17, 1990', 'Mar 1, 2018']); }); it('CRUD: should recalculate summary functions on updateRow', () => { const productNameCell = grid.getCellByColumn(0, 'ProductName'); const unitsInStockCell = grid.getCellByColumn(0, 'UnitsInStock'); expect(productNameCell.value).toBe('Chai'); expect(unitsInStockCell.value).toBe(2760); grid.updateRow({ ProductID: 1, ProductName: 'Spearmint', InStock: true, UnitsInStock: 510000, OrderDate: new Date('1984-03-21') }, 1); fix.detectChanges(); expect(productNameCell.value).toBe('Spearmint'); expect(unitsInStockCell.value).toBe(510000); const summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '510,000', '546,244', '54,624.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', 'Mar 21, 1984', 'Dec 25, 2025']); }); it('CRUD: should recalculate summary functions on cell update', () => { const unitsInStockCell = grid.getCellByColumn(0, 'UnitsInStock'); unitsInStockCell.update(99000); fix.detectChanges(); let summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '99,000', '135,244', '13,524.4']); unitsInStockCell.update(-12); fix.detectChanges(); summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '-12', '20,000', '36,232', '3,623.2']); }); it('Pinning: should display all active summaries after column pinning', () => { grid.pinColumn('UnitsInStock'); grid.pinColumn('ProductID'); fix.detectChanges(); const summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); }); it('CRUD: Apply filter and update cell', () => { grid.filter('ProductName', 'ch', IgxStringFilteringOperand.instance().condition('contains')); fix.detectChanges(); let summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['4', '52', '20,000', '29,810', '7,452.5']); const cell = grid.getCellByColumn(2, 'ProductName'); cell.update('Teatime Cocoa Biscuits'); fix.detectChanges(); summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['3']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '52', '20,000', '22,812', '7,604']); }); }); }); describe('Keyboard Navigation', () => { let fix; let grid: IgxGridComponent; beforeEach(() => { fix = TestBed.createComponent(SummariesGroupByComponent); grid = fix.componentInstance.grid; setupGridScrollDetection(fix, grid); grid.width = '800px'; grid.height = '800px'; fix.detectChanges(); }); afterEach(() => { clearGridSubs(); }); it('should be able to select summaries with arrow keys', async () => { const gridFooter = GridFunctions.getGridFooter(fix); let summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.focusSummaryCell(fix, summaryRow, 0); for (let i = 0; i < 5; i++) { GridSummaryFunctions.verifySummaryCellActive(fix, summaryRow, i); UIInteractions.triggerEventHandlerKeyDown('ArrowRight', gridFooter); await wait(DEBOUNCETIME); fix.detectChanges(); } summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '25', '50', '293', '36.625']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['8']); for (let i = 5; i > 0; i--) { GridSummaryFunctions.verifySummaryCellActive(fix, summaryRow, i); UIInteractions.triggerEventHandlerKeyDown('ArrowLeft', gridFooter); await wait(DEBOUNCETIME); fix.detectChanges(); } summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '17', '847', '2,188', '273.5']); }); it('should be able to navigate with Arrow keys and Ctrl', async () => { const gridFooter = GridFunctions.getGridFooter(fix); let summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.focusSummaryCell(fix, summaryRow, 1); UIInteractions.triggerEventHandlerKeyDown('ArrowRight', gridFooter, false, false, true); await wait(DEBOUNCETIME); fix.detectChanges(); GridSummaryFunctions.verifySummaryCellActive(fix, summaryRow, 5); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '25', '50', '293', '36.625']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['8']); UIInteractions.triggerEventHandlerKeyDown('ArrowLeft', gridFooter, false, false, true); await wait(DEBOUNCETIME); fix.detectChanges(); GridSummaryFunctio