igniteui-angular-sovn
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
1,000 lines (842 loc) • 68.6 kB
text/typescript
import { configureTestSuite } from '../../test-utils/configure-suite';
import { TestBed, fakeAsync, tick, waitForAsync, ComponentFixture } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { IgxGridComponent } from './grid.component';
import { SampleTestData } from '../../test-utils/sample-test-data.spec';
import { ViewChild, Component } from '@angular/core';
import { IgxColumnLayoutComponent } from '../columns/column-layout.component';
import { wait, UIInteractions } from '../../test-utils/ui-interactions.spec';
import { DefaultSortingStrategy, SortingDirection } from '../../data-operations/sorting-strategy';
import { GridFunctions, GRID_MRL_BLOCK } from '../../test-utils/grid-functions.spec';
import { ControlsFunction } from '../../test-utils/controls-functions.spec';
import { IgxColumnComponent } from '../columns/column.component';
import { IgxGridToolbarComponent } from '../toolbar/grid-toolbar.component';
import { IgxGridToolbarActionsComponent } from '../toolbar/common';
import { IgxGridToolbarHidingComponent } from '../toolbar/grid-toolbar-hiding.component';
import { IgxGridToolbarPinningComponent } from '../toolbar/grid-toolbar-pinning.component';
import { NgFor, NgIf } from '@angular/common';
type FixtureType = ColumnLayoutGroupingTestComponent | ColumnLayouHidingTestComponent | ColumnLayoutResizingTestComponent
| ColumnLayoutPinningTestComponent;
interface ColGroupsType {
group: string;
hidden?: boolean;
pinned?: boolean;
columns: any[];
}
describe('IgxGrid - multi-row-layout Integration #grid - ', () => {
let fixture: ComponentFixture<FixtureType>;
let grid: IgxGridComponent;
configureTestSuite((() => {
return TestBed.configureTestingModule({
imports: [
NoopAnimationsModule,
ColumnLayoutPinningTestComponent,
ColumnLayoutFilteringTestComponent,
ColumnLayouHidingTestComponent,
ColumnLayoutGroupingTestComponent,
ColumnLayoutResizingTestComponent
]
});
}));
describe('Hiding ', () => {
beforeEach(() => {
fixture = TestBed.createComponent(ColumnLayouHidingTestComponent);
fixture.detectChanges();
grid = fixture.componentInstance.grid;
});
it('should allow setting a whole group as hidden/shown.', () => {
// group 1 should be hidden - all child columns should be hidden
expect(grid.getColumnByName('group1').hidden).toBeTruthy();
expect(grid.getColumnByName('PostalCode').hidden).toBeTruthy();
expect(grid.getColumnByName('City').hidden).toBeTruthy();
expect(grid.getColumnByName('Country').hidden).toBeTruthy();
expect(grid.getColumnByName('Address').hidden).toBeTruthy();
expect(grid.getColumnByName('group2').hidden).toBeFalsy();
expect(grid.getColumnByName('ID').hidden).toBeFalsy();
expect(grid.getColumnByName('CompanyName').hidden).toBeFalsy();
expect(grid.getColumnByName('ContactName').hidden).toBeFalsy();
expect(grid.getColumnByName('ContactTitle').hidden).toBeFalsy();
let gridFirstRow = grid.rowList.first;
// headers are aligned to cells
GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow);
GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, fixture.componentInstance.colGroups.slice(1, 2));
// show group
fixture.componentInstance.colGroups[0].hidden = false;
fixture.detectChanges();
fixture.detectChanges();
expect(grid.getColumnByName('group1').hidden).toBeFalsy();
expect(grid.getColumnByName('PostalCode').hidden).toBeFalsy();
expect(grid.getColumnByName('City').hidden).toBeFalsy();
expect(grid.getColumnByName('Country').hidden).toBeFalsy();
expect(grid.getColumnByName('Address').hidden).toBeFalsy();
expect(grid.getColumnByName('group2').hidden).toBeFalsy();
expect(grid.getColumnByName('ID').hidden).toBeFalsy();
expect(grid.getColumnByName('CompanyName').hidden).toBeFalsy();
expect(grid.getColumnByName('ContactName').hidden).toBeFalsy();
expect(grid.getColumnByName('ContactTitle').hidden).toBeFalsy();
// headers are aligned to cells
gridFirstRow = grid.rowList.first;
GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow);
GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, fixture.componentInstance.colGroups);
// hide the other group
fixture.componentInstance.colGroups[1].hidden = true;
fixture.detectChanges();
fixture.detectChanges();
expect(grid.getColumnByName('PostalCode').hidden).toBeFalsy();
expect(grid.getColumnByName('City').hidden).toBeFalsy();
expect(grid.getColumnByName('Country').hidden).toBeFalsy();
expect(grid.getColumnByName('Address').hidden).toBeFalsy();
expect(grid.getColumnByName('ID').hidden).toBeTruthy();
expect(grid.getColumnByName('CompanyName').hidden).toBeTruthy();
expect(grid.getColumnByName('ContactName').hidden).toBeTruthy();
expect(grid.getColumnByName('ContactTitle').hidden).toBeTruthy();
gridFirstRow = grid.rowList.first;
// headers are aligned to cells
GridFunctions.verifyLayoutHeadersAreAligned(grid, grid.rowList.first);
GridFunctions.verifyDOMMatchesLayoutSettings(grid, grid.rowList.first, fixture.componentInstance.colGroups.slice(0, 1));
});
it('should hide/show whole group if a single child column is hidden/shown.', () => {
// show PostalCode
grid.getColumnByName('PostalCode').hidden = false;
fixture.detectChanges();
// everything should be shown
expect(grid.getColumnByName('group1').hidden).toBeFalsy();
expect(grid.getColumnByName('PostalCode').hidden).toBeFalsy();
expect(grid.getColumnByName('City').hidden).toBeFalsy();
expect(grid.getColumnByName('Country').hidden).toBeFalsy();
expect(grid.getColumnByName('Address').hidden).toBeFalsy();
expect(grid.getColumnByName('group2').hidden).toBeFalsy();
expect(grid.getColumnByName('ID').hidden).toBeFalsy();
expect(grid.getColumnByName('CompanyName').hidden).toBeFalsy();
expect(grid.getColumnByName('ContactName').hidden).toBeFalsy();
expect(grid.getColumnByName('ContactTitle').hidden).toBeFalsy();
// hide ContactTitle
grid.getColumnByName('ContactTitle').hidden = true;
fixture.detectChanges();
// group2 should be hidden
expect(grid.getColumnByName('group1').hidden).toBeFalsy();
expect(grid.getColumnByName('PostalCode').hidden).toBeFalsy();
expect(grid.getColumnByName('City').hidden).toBeFalsy();
expect(grid.getColumnByName('Country').hidden).toBeFalsy();
expect(grid.getColumnByName('Address').hidden).toBeFalsy();
expect(grid.getColumnByName('group2').hidden).toBeTruthy();
expect(grid.getColumnByName('ID').hidden).toBeTruthy();
expect(grid.getColumnByName('CompanyName').hidden).toBeTruthy();
expect(grid.getColumnByName('ContactName').hidden).toBeTruthy();
expect(grid.getColumnByName('ContactTitle').hidden).toBeTruthy();
});
it('verify visible column indexes when hide/show a column', () => {
expect(grid.getColumnByName('ID').visibleIndex).toBe(0);
expect(grid.getColumnByName('CompanyName').visibleIndex).toBe(1);
expect(grid.getColumnByName('ContactName').visibleIndex).toBe(2);
expect(grid.getColumnByName('ContactTitle').visibleIndex).toBe(3);
// show PostalCode
grid.getColumnByName('PostalCode').hidden = false;
fixture.detectChanges();
expect(grid.getColumnByName('ID').visibleIndex).toBe(1);
expect(grid.getColumnByName('CompanyName').visibleIndex).toBe(2);
expect(grid.getColumnByName('ContactName').visibleIndex).toBe(3);
expect(grid.getColumnByName('ContactTitle').visibleIndex).toBe(6);
expect(grid.getColumnByName('PostalCode').visibleIndex).toBe(0);
expect(grid.getColumnByName('City').visibleIndex).toBe(4);
expect(grid.getColumnByName('Country').visibleIndex).toBe(5);
expect(grid.getColumnByName('Address').visibleIndex).toBe(7);
// hide PostalCode
grid.getColumnByName('PostalCode').hidden = true;
fixture.detectChanges();
expect(grid.getColumnByName('PostalCode').visibleIndex).toBe(-1);
expect(grid.getColumnByName('City').visibleIndex).toBe(-1);
expect(grid.getColumnByName('Country').visibleIndex).toBe(-1);
expect(grid.getColumnByName('Address').visibleIndex).toBe(-1);
// show PostalCode
grid.getColumnByName('PostalCode').hidden = false;
fixture.detectChanges();
expect(grid.getColumnByName('PostalCode').visibleIndex).toBe(0);
expect(grid.getColumnByName('City').visibleIndex).toBe(4);
expect(grid.getColumnByName('Country').visibleIndex).toBe(5);
expect(grid.getColumnByName('Address').visibleIndex).toBe(7);
});
it('should work with horizontal virtualization when some groups are hidden/shown.', async () => {
const uniqueGroups: ColGroupsType[] = [
{
group: 'group1',
hidden: true,
// total colspan 3
columns: [
{ field: 'Address', rowStart: 1, colStart: 1, colEnd: 4, rowEnd: 3 },
{ field: 'County', rowStart: 3, colStart: 1 },
{ field: 'Region', rowStart: 3, colStart: 2 },
{ field: 'City', rowStart: 3, colStart: 3 }
]
},
{
group: 'group2',
// total colspan 2
columns: [
{ field: 'CompanyName', rowStart: 1, colStart: 1 },
{ field: 'Address', rowStart: 1, colStart: 2 },
{ field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 }
]
},
{
group: 'group3',
// total colspan 1
columns: [
{ field: 'Phone', rowStart: 1, colStart: 1 },
{ field: 'Fax', rowStart: 2, colStart: 1, rowEnd: 4 }
]
},
{
group: 'group4',
// total colspan 4
columns: [
{ field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 },
{ field: 'Phone', rowStart: 1, colStart: 3, rowEnd: 3 },
{ field: 'Address', rowStart: 1, colStart: 4, rowEnd: 4 },
{ field: 'Region', rowStart: 2, colStart: 1 },
{ field: 'City', rowStart: 2, colStart: 2 },
{ field: 'ContactName', rowStart: 3, colStart: 1, colEnd: 4 },
]
}
];
fixture.componentInstance.colGroups = uniqueGroups;
grid.columnWidth = '200px';
fixture.componentInstance.grid.width = '600px';
fixture.detectChanges();
const gridFirstRow = grid.rowList.first;
// group1 should be hidden on init, check DOM
GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow);
GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, fixture.componentInstance.colGroups.slice(1));
// check virtualization state
// 4 groups in total - 1 is hidden
const horizontalVirtualization = grid.rowList.first.virtDirRow;
expect(grid.hasHorizontalScroll()).toBeTruthy();
expect(horizontalVirtualization.igxForOf.length).toBe(3);
// check order is correct
expect(horizontalVirtualization.igxForOf[0]).toBe(grid.getColumnByName('group2'));
expect(horizontalVirtualization.igxForOf[1]).toBe(grid.getColumnByName('group3'));
expect(horizontalVirtualization.igxForOf[2]).toBe(grid.getColumnByName('group4'));
// check their sizes are correct
expect(horizontalVirtualization.getSizeAt(0)).toBe(2 * 200);
expect(horizontalVirtualization.getSizeAt(1)).toBe(1 * 200);
expect(horizontalVirtualization.getSizeAt(2)).toBe(4 * 200);
// check total widths sum
let horizonatalScrElem = horizontalVirtualization.getScroll();
// 7 column span in total
let totalExpected = 7 * 200;
expect(parseInt((horizonatalScrElem.children[0] as HTMLElement).style.width, 10)).toBe(totalExpected);
// hide group 3
grid.getColumnByName('group3').hidden = true;
fixture.detectChanges();
// check virtualization state
// 4 groups in total - 2 is hidden
expect(grid.hasHorizontalScroll()).toBeTruthy();
expect(horizontalVirtualization.igxForOf.length).toBe(2);
// check order is correct
expect(horizontalVirtualization.igxForOf[0]).toBe(grid.getColumnByName('group2'));
expect(horizontalVirtualization.igxForOf[1]).toBe(grid.getColumnByName('group4'));
// check their sizes are correct
expect(horizontalVirtualization.getSizeAt(0)).toBe(2 * 200);
expect(horizontalVirtualization.getSizeAt(1)).toBe(4 * 200);
// check total widths sum
horizonatalScrElem = horizontalVirtualization.getScroll();
// 7 column span in total
totalExpected = 6 * 200;
expect(parseInt((horizonatalScrElem.children[0] as HTMLElement).style.width, 10)).toBe(totalExpected);
// show group1
grid.getColumnByName('group1').hidden = false;
fixture.detectChanges();
// check virtualization state
// 4 groups in total - 1 is hidden
expect(grid.hasHorizontalScroll()).toBeTruthy();
expect(horizontalVirtualization.igxForOf.length).toBe(3);
// check order is correct
expect(horizontalVirtualization.igxForOf[0]).toBe(grid.getColumnByName('group1'));
expect(horizontalVirtualization.igxForOf[1]).toBe(grid.getColumnByName('group2'));
expect(horizontalVirtualization.igxForOf[2]).toBe(grid.getColumnByName('group4'));
// check their sizes are correct
expect(horizontalVirtualization.getSizeAt(0)).toBe(3 * 200);
expect(horizontalVirtualization.getSizeAt(1)).toBe(2 * 200);
expect(horizontalVirtualization.getSizeAt(2)).toBe(4 * 200);
// check total widths sum
horizonatalScrElem = horizontalVirtualization.getScroll();
// 7 column span in total
totalExpected = 9 * 200;
expect(parseInt((horizonatalScrElem.children[0] as HTMLElement).style.width, 10)).toBe(totalExpected);
// check last column group can be scrolled in view
horizontalVirtualization.scrollTo(2);
await wait(100);
fixture.detectChanges();
const lastCell = grid.rowList.first.cells.toArray()[5];
expect(lastCell.column.field).toBe('Address');
expect(lastCell.column.parent.field).toBe('group4');
expect(lastCell.nativeElement.getBoundingClientRect().right)
.toEqual(grid.tbody.nativeElement.getBoundingClientRect().right);
});
it('UI - hidden columns count and drop-down items text in hiding toolbar should be correct when group is hidden/shown. ',
waitForAsync(async () => {
// enable toolbar for hiding
fixture.componentInstance.showToolbar = true;
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();
const hidingButton = GridFunctions.getColumnHidingButton(fixture);
hidingButton.click();
fixture.detectChanges();
// should show count for actual hidden igxColumns
expect(parseInt(hidingButton.querySelector('span').textContent.trim(), 10)).toBe(4);
const columnChooserElement = GridFunctions.getColumnHidingElement(fixture);
const checkboxes = columnChooserElement.queryAll(By.css('igx-checkbox'));
// should show 2 checkboxes - one for each group
expect(checkboxes.length).toBe(2);
expect(checkboxes[0].query(By.css('.igx-checkbox__label')).nativeElement.textContent.trim()).toBe('group1');
expect(checkboxes[1].query(By.css('.igx-checkbox__label')).nativeElement.textContent.trim()).toBe('group2');
// verify checked state
expect(checkboxes[0].componentInstance.checked).toBeFalse();
expect(checkboxes[1].componentInstance.checked).toBeTrue();
}));
it(`UI - toggling column checkbox checked state successfully changes the column's hidden state. `, waitForAsync(async () => {
// enable toolbar for hiding
fixture.componentInstance.showToolbar = true;
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();
const hidingButton = GridFunctions.getColumnHidingButton(fixture);
hidingButton.click();
fixture.detectChanges();
const verifyCheckbox = ControlsFunction.verifyCheckbox;
const columnChooserElement = GridFunctions.getColumnHidingElement(fixture);
const checkbox = ControlsFunction.getCheckboxInput('group1', columnChooserElement);
verifyCheckbox('group1', false, false, columnChooserElement);
const column = grid.getColumnByName('group1');
expect(column.hidden).toBeTrue();
let gridFirstRow = grid.rowList.first;
GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow);
GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, fixture.componentInstance.colGroups.slice(1));
const checkboxEl = ControlsFunction.getCheckboxElement('group1', columnChooserElement);
checkboxEl.triggerEventHandler('click', new Event('click'));
fixture.detectChanges();
expect(checkbox.checked).toBe(true);
expect(column.hidden).toBeFalse();
gridFirstRow = grid.rowList.first;
GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow);
GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, fixture.componentInstance.colGroups);
checkboxEl.triggerEventHandler('click', new Event('click'));
fixture.detectChanges();
expect(checkbox.checked).toBe(false);
expect(column.hidden).toBeTrue();
}));
});
describe('Pinning ', () => {
beforeEach(() => {
fixture = TestBed.createComponent(ColumnLayoutPinningTestComponent);
fixture.detectChanges();
grid = fixture.componentInstance.grid;
});
it('should allow pinning/unpinning a whole group.', () => {
// group 1 should be pinned - all child columns should be pinned
expect(grid.getColumnByName('PostalCode').pinned).toBeTruthy();
expect(grid.getColumnByName('City').pinned).toBeTruthy();
expect(grid.getColumnByName('Country').pinned).toBeTruthy();
expect(grid.getColumnByName('Address').pinned).toBeTruthy();
expect(grid.getColumnByName('ID').pinned).toBeFalsy();
expect(grid.getColumnByName('CompanyName').pinned).toBeFalsy();
expect(grid.getColumnByName('ContactName').pinned).toBeFalsy();
expect(grid.getColumnByName('ContactTitle').pinned).toBeFalsy();
// headers are aligned to cells
// TODO MRL
let gridFirstRow = grid.rowList.first;
GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow, true);
GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, fixture.componentInstance.colGroups);
// unpin group
fixture.componentInstance.colGroups[0].pinned = false;
fixture.detectChanges();
expect(grid.getColumnByName('PostalCode').pinned).toBeFalsy();
expect(grid.getColumnByName('City').pinned).toBeFalsy();
expect(grid.getColumnByName('Country').pinned).toBeFalsy();
expect(grid.getColumnByName('Address').pinned).toBeFalsy();
expect(grid.getColumnByName('ID').pinned).toBeFalsy();
expect(grid.getColumnByName('CompanyName').pinned).toBeFalsy();
expect(grid.getColumnByName('ContactName').pinned).toBeFalsy();
expect(grid.getColumnByName('ContactTitle').pinned).toBeFalsy();
gridFirstRow = grid.rowList.first;
// headers are aligned to cells
GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow);
GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, fixture.componentInstance.colGroups);
// pin the other group
fixture.componentInstance.colGroups[1].pinned = true;
fixture.detectChanges();
expect(grid.getColumnByName('PostalCode').pinned).toBeFalsy();
expect(grid.getColumnByName('City').pinned).toBeFalsy();
expect(grid.getColumnByName('Country').pinned).toBeFalsy();
expect(grid.getColumnByName('Address').pinned).toBeFalsy();
expect(grid.getColumnByName('ID').pinned).toBeTruthy();
expect(grid.getColumnByName('CompanyName').pinned).toBeTruthy();
expect(grid.getColumnByName('ContactName').pinned).toBeTruthy();
expect(grid.getColumnByName('ContactTitle').pinned).toBeTruthy();
});
it('should pin/unpin whole group if a single child column is pinned/unpinned.', () => {
// group 1 should be pinned - all child columns should be pinned
expect(grid.getColumnByName('PostalCode').pinned).toBeTruthy();
expect(grid.getColumnByName('City').pinned).toBeTruthy();
expect(grid.getColumnByName('Country').pinned).toBeTruthy();
expect(grid.getColumnByName('Address').pinned).toBeTruthy();
expect(grid.getColumnByName('ID').pinned).toBeFalsy();
expect(grid.getColumnByName('CompanyName').pinned).toBeFalsy();
expect(grid.getColumnByName('ContactName').pinned).toBeFalsy();
expect(grid.getColumnByName('ContactTitle').pinned).toBeFalsy();
grid.unpinColumn('City');
fixture.detectChanges();
expect(grid.getColumnByName('PostalCode').pinned).toBeFalsy();
expect(grid.getColumnByName('City').pinned).toBeFalsy();
expect(grid.getColumnByName('Country').pinned).toBeFalsy();
expect(grid.getColumnByName('Address').pinned).toBeFalsy();
expect(grid.getColumnByName('ID').pinned).toBeFalsy();
expect(grid.getColumnByName('CompanyName').pinned).toBeFalsy();
expect(grid.getColumnByName('ContactName').pinned).toBeFalsy();
expect(grid.getColumnByName('ContactTitle').pinned).toBeFalsy();
grid.pinColumn('ContactName');
fixture.detectChanges();
expect(grid.getColumnByName('PostalCode').pinned).toBeFalsy();
expect(grid.getColumnByName('City').pinned).toBeFalsy();
expect(grid.getColumnByName('Country').pinned).toBeFalsy();
expect(grid.getColumnByName('Address').pinned).toBeFalsy();
expect(grid.getColumnByName('ID').pinned).toBeTruthy();
expect(grid.getColumnByName('CompanyName').pinned).toBeTruthy();
expect(grid.getColumnByName('ContactName').pinned).toBeTruthy();
expect(grid.getColumnByName('ContactTitle').pinned).toBeTruthy();
});
it('should emit columnPin event with correct parameters', () => {
let allArgs = [];
grid.columnPin.subscribe((args) => {
allArgs.push(args);
});
grid.unpinColumn('City');
fixture.detectChanges();
// should unpin parent and all child cols - 4 child + 1 parent
expect(allArgs.length).toBe(5);
expect(allArgs[0].column instanceof IgxColumnLayoutComponent).toBeTruthy();
expect(allArgs[0].isPinned).toBeTrue();
expect(allArgs[1].column.field).toBe('PostalCode');
expect(allArgs[1].isPinned).toBeTrue();
expect(allArgs[2].column.field).toBe('City');
expect(allArgs[2].isPinned).toBeTrue();
expect(allArgs[3].column.field).toBe('Country');
expect(allArgs[3].isPinned).toBeTrue();
expect(allArgs[4].column.field).toBe('Address');
expect(allArgs[4].isPinned).toBeTrue();
allArgs = [];
grid.pinColumn('ID');
fixture.detectChanges();
// should pin parent and all child cols - 4 child + 1 parent
expect(allArgs.length).toBe(5);
expect(allArgs[0].column instanceof IgxColumnLayoutComponent).toBeTruthy();
expect(allArgs[0].isPinned).toBeFalse();
expect(allArgs[1].column.field).toBe('ID');
expect(allArgs[1].isPinned).toBeFalse();
expect(allArgs[2].column.field).toBe('CompanyName');
expect(allArgs[2].isPinned).toBeFalse();
expect(allArgs[3].column.field).toBe('ContactName');
expect(allArgs[3].isPinned).toBeFalse();
expect(allArgs[4].column.field).toBe('ContactTitle');
expect(allArgs[4].isPinned).toBeFalse();
});
it('should work with horizontal virtualization on the unpinned groups.', async () => {
const uniqueGroups = [
{
group: 'group1',
// total colspan 3
columns: [
{ field: 'Address', rowStart: 1, colStart: 1, colEnd: 4, rowEnd: 3 },
{ field: 'County', rowStart: 3, colStart: 1 },
{ field: 'Region', rowStart: 3, colStart: 2 },
{ field: 'City', rowStart: 3, colStart: 3 }
]
},
{
group: 'group2',
// total colspan 2
columns: [
{ field: 'CompanyName', rowStart: 1, colStart: 1 },
{ field: 'Address', rowStart: 1, colStart: 2 },
{ field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 }
]
},
{
group: 'group3',
// total colspan 1
columns: [
{ field: 'Phone', rowStart: 1, colStart: 1 },
{ field: 'Fax', rowStart: 2, colStart: 1, rowEnd: 4 }
]
},
{
group: 'group4',
// total colspan 4
columns: [
{ field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 },
{ field: 'Phone', rowStart: 1, colStart: 3, rowEnd: 3 },
{ field: 'Address', rowStart: 1, colStart: 4, rowEnd: 4 },
{ field: 'Region', rowStart: 2, colStart: 1 },
{ field: 'City', rowStart: 2, colStart: 2 },
{ field: 'ContactName', rowStart: 3, colStart: 1, colEnd: 4 },
]
}
];
fixture.componentInstance.colGroups = uniqueGroups;
fixture.detectChanges();
grid.columnWidth = '200px';
fixture.componentInstance.grid.width = '600px';
fixture.detectChanges();
// pin group3
grid.pinColumn('group3');
fixture.detectChanges();
// check group 3 is pinned
expect(grid.getColumnByName('group3').pinned).toBeTruthy();
expect(grid.getColumnByName('Fax').pinned).toBeTruthy();
expect(grid.getColumnByName('Phone').pinned).toBeTruthy();
const gridFirstRow = grid.rowList.first;
GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, fixture.componentInstance.colGroups.slice(2, 3));
// headers are aligned to cells
GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow, true);
// check virtualization state
// 4 groups in total - 1 is pinned
const horizontalVirtualization = grid.rowList.first.virtDirRow;
expect(grid.hasHorizontalScroll()).toBeTruthy();
expect(horizontalVirtualization.igxForOf.length).toBe(3);
// check order is correct
expect(horizontalVirtualization.igxForOf[0]).toBe(grid.getColumnByName('group1'));
expect(horizontalVirtualization.igxForOf[1]).toBe(grid.getColumnByName('group2'));
expect(horizontalVirtualization.igxForOf[2]).toBe(grid.getColumnByName('group4'));
// check their sizes are correct
expect(horizontalVirtualization.getSizeAt(0)).toBe(3 * 200);
expect(horizontalVirtualization.getSizeAt(1)).toBe(2 * 200);
expect(horizontalVirtualization.getSizeAt(2)).toBe(4 * 200);
// check total widths sum
const horizonatalScrElem = horizontalVirtualization.getScroll();
// 9 column span in total
const totalExpected = 9 * 200;
expect(parseInt((horizonatalScrElem.children[0] as HTMLElement).style.width, 10)).toBe(totalExpected);
// check last column group can be scrolled in view
horizontalVirtualization.scrollTo(2);
await wait(100);
fixture.detectChanges();
const lastCell = grid.rowList.first.cells.toArray()[5];
expect(lastCell.column.field).toBe('Address');
expect(lastCell.column.parent.field).toBe('group4');
expect(Math.round(lastCell.nativeElement.getBoundingClientRect().right) -
grid.tbody.nativeElement.getBoundingClientRect().right)
.toBeLessThanOrEqual(2);
});
it('UI - pinned columns count and drop-down items text in pinning toolbar should be correct when group is pinned. ',
waitForAsync(async () => {
// enable toolbar for pinning
fixture.componentInstance.showToolbar = true;
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();
const pinningButton = GridFunctions.getColumnPinningButton(fixture);
const pinningButtonLabel = pinningButton.querySelector('span');
pinningButton.click();
fixture.detectChanges();
// should show count for actual igxColumns displayed in the pinned area
expect(parseInt(pinningButtonLabel.textContent.trim(), 10)).toBe(4);
const columnChooserElement = GridFunctions.getColumnPinningElement(fixture);
const checkboxes = columnChooserElement.queryAll(By.css('igx-checkbox'));
// should show 2 checkboxes - one for each group
expect(checkboxes.length).toBe(2);
expect(checkboxes[0].query(By.css('.igx-checkbox__label')).nativeElement.textContent.trim()).toBe('group1');
expect(checkboxes[1].query(By.css('.igx-checkbox__label')).nativeElement.textContent.trim()).toBe('group2');
// verify checked state
expect(checkboxes[0].componentInstance.checked).toBeTruthy();
expect(checkboxes[1].componentInstance.checked).toBeFalsy();
}));
it(`UI - toggling column checkbox checked state successfully changes the column's pinned state. `, waitForAsync(async () => {
const uniqueGroups = [
{
group: 'group1',
// total colspan 3
columns: [
{ field: 'Address', rowStart: 1, colStart: 1, colEnd: 4, rowEnd: 3 },
{ field: 'County', rowStart: 3, colStart: 1 },
{ field: 'Region', rowStart: 3, colStart: 2 },
{ field: 'City', rowStart: 3, colStart: 3 }
]
},
{
group: 'group2',
// total colspan 2
columns: [
{ field: 'CompanyName', rowStart: 1, colStart: 1 },
{ field: 'Address', rowStart: 1, colStart: 2 },
{ field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 }
]
},
{
group: 'group3',
// total colspan 1
columns: [
{ field: 'Phone', rowStart: 1, colStart: 1 },
{ field: 'Fax', rowStart: 2, colStart: 1, rowEnd: 4 }
]
},
{
group: 'group4',
// total colspan 4
columns: [
{ field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 },
{ field: 'Phone', rowStart: 1, colStart: 3, rowEnd: 3 },
{ field: 'Address', rowStart: 1, colStart: 4, rowEnd: 4 },
{ field: 'Region', rowStart: 2, colStart: 1 },
{ field: 'City', rowStart: 2, colStart: 2 },
{ field: 'ContactName', rowStart: 3, colStart: 1, colEnd: 4 },
]
}
];
fixture.componentInstance.showToolbar = true;
fixture.componentInstance.colGroups = uniqueGroups;
grid.columnWidth = '200px';
fixture.componentInstance.grid.width = '1000px';
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();
const pinningButton = GridFunctions.getColumnPinningButton(fixture);
pinningButton.click();
fixture.detectChanges();
const columnChooserElement = GridFunctions.getColumnPinningElement(fixture);
const verifyCheckbox = ControlsFunction.verifyCheckbox;
const checkbox = ControlsFunction.getCheckboxInput('group1', columnChooserElement);
verifyCheckbox('group1', false, false, columnChooserElement);
const column = grid.getColumnByName('group1');
expect(column.pinned).toBeFalsy();
const checkboxEl = ControlsFunction.getCheckboxElement('group1', columnChooserElement);
checkboxEl.triggerEventHandler('click', new Event('click'));
fixture.detectChanges();
expect(checkbox.checked).toBe(true);
expect(column.pinned).toBeTruthy();
checkboxEl.triggerEventHandler('click', new Event('click'));
fixture.detectChanges();
expect(checkbox.checked).toBe(false);
expect(column.pinned).toBeFalsy();
}));
it('should work when pinning group with columns that do not have and the unpinned group has width in percentages.', async () => {
const uniqueGroups = [
{
group: 'group1',
// total colspan 3
columns: [
{ field: 'Address', rowStart: 1, colStart: 1, colEnd: 4, rowEnd: 3 },
{ field: 'County', rowStart: 3, colStart: 1 },
{ field: 'Region', rowStart: 3, colStart: 2 },
{ field: 'City', rowStart: 3, colStart: 3 }
]
},
{
group: 'group2',
// total colspan 2
columns: [
{ field: 'CompanyName', rowStart: 1, colStart: 1, width: '50%' },
{ field: 'Address', rowStart: 1, colStart: 2, width: '15%' },
{ field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 }
]
}
];
fixture.componentInstance.colGroups = uniqueGroups;
fixture.componentInstance.grid.width = (800 + grid.scrollSize) + 'px';
fixture.detectChanges();
// pin group3
grid.pinColumn('group1');
fixture.detectChanges();
// check group 3 is pinned
expect(grid.getColumnByName('group1').pinned).toBeTruthy();
expect(grid.getColumnByName('Address').pinned).toBeTruthy();
expect(grid.getColumnByName('County').pinned).toBeTruthy();
const gridFirstRow = grid.rowList.first;
GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, fixture.componentInstance.colGroups.slice(2, 3));
// headers are aligned to cells
GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow, true);
// check virtualization state
const horizontalVirtualization = grid.rowList.first.virtDirRow;
expect(grid.hasHorizontalScroll()).toBeTruthy();
expect(horizontalVirtualization.igxForOf.length).toBe(1);
expect(horizontalVirtualization.igxForOf[0]).toBe(grid.getColumnByName('group2'));
// check their sizes are correct
const totalExpected = 0.65 * 800;
expect(horizontalVirtualization.getSizeAt(0)).toBe(totalExpected);
// check width scrollbar
const horizonatalScrElem = horizontalVirtualization.getScroll();
expect(parseInt((horizonatalScrElem.children[0] as HTMLElement).style.width, 10)).toBe(totalExpected);
});
});
describe('Filtering ', () => {
beforeEach(() => {
fixture = TestBed.createComponent(ColumnLayoutFilteringTestComponent);
fixture.detectChanges();
grid = fixture.componentInstance.grid;
});
it('should enforce excel style filtering.', () => {
const filteringCells = fixture.debugElement.queryAll(By.css('igx-grid-filtering-cell'));
expect(filteringCells.length).toBe(0);
const filterIcons = fixture.debugElement.queryAll(By.css('.igx-excel-filter__icon'));
expect(filterIcons.length).not.toBe(0);
const gridFirstRow = grid.rowList.first;
// headers are aligned to cells
GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow, true);
GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, fixture.componentInstance.colGroups);
});
it('should render unpin and hide column buttons into the excel style filter', () => {
const filterIcons = fixture.debugElement.queryAll(By.css('.igx-excel-filter__icon'));
expect(filterIcons.length).not.toBe(0);
filterIcons[0].nativeElement.click();
fixture.detectChanges();
const excelMenu = grid.nativeElement.querySelector('.igx-excel-filter__menu');
const unpinComponent = excelMenu.querySelector('.igx-excel-filter__actions-unpin');
const hideComponent = excelMenu.querySelector('.igx-excel-filter__actions-hide');
expect(unpinComponent).toBeDefined();
expect(hideComponent).toBeDefined();
});
});
describe('GroupBy ', () => {
beforeEach(() => {
fixture = TestBed.createComponent(ColumnLayoutGroupingTestComponent);
fixture.detectChanges();
grid = fixture.componentInstance.grid;
});
it('should render rows correctly when grouped by a column and scrolling to bottom should not leave empty space.', async () => {
grid.height = '600px';
grid.groupBy({
dir: SortingDirection.Desc,
fieldName: 'Country',
ignoreCase: false,
strategy: DefaultSortingStrategy.instance()
});
fixture.detectChanges();
expect(grid.rowList.length).toEqual(8);
expect((grid.verticalScrollContainer.getScroll().children[0] as HTMLElement).offsetHeight -
grid.verticalScrollContainer.getScroll().offsetHeight).toBeGreaterThan(0);
const lastIndex = grid.data.length + grid.groupsRecords.length - 1;
grid.verticalScrollContainer.scrollTo(lastIndex);
await wait(100);
fixture.detectChanges();
const scrollTop = grid.verticalScrollContainer.getScroll().scrollTop;
const scrollHeight = grid.verticalScrollContainer.getScroll().scrollHeight;
const tbody = fixture.debugElement.query(By.css('.igx-grid__tbody')).nativeElement;
const scrolledToBottom = Math.round(scrollTop + tbody.scrollHeight) === scrollHeight;
expect(grid.rowList.length).toEqual(8);
expect(scrolledToBottom).toBeTruthy();
const lastRowOffset = grid.rowList.last.element.nativeElement.offsetTop +
grid.rowList.last.element.nativeElement.offsetHeight + parseInt(tbody.children[0].children[0].style.top, 10);
expect(lastRowOffset).toEqual(tbody.scrollHeight);
});
it('should render rows correctly and collapsing all should render all groups and there should be no scrollbar.', fakeAsync(() => {
grid.height = '600px';
fixture.detectChanges();
grid.groupBy({
dir: SortingDirection.Desc,
fieldName: 'Country',
ignoreCase: false,
strategy: DefaultSortingStrategy.instance()
});
fixture.detectChanges();
expect(grid.rowList.length).toEqual(8);
expect((grid.verticalScrollContainer.getScroll().children[0] as HTMLElement).offsetHeight -
grid.verticalScrollContainer.getScroll().offsetHeight).toBeGreaterThan(0);
grid.toggleAllGroupRows();
tick(100);
fixture.detectChanges();
tick(100);
fixture.detectChanges();
expect(grid.rowList.length).toEqual(12);
expect((grid.verticalScrollContainer.getScroll().children[0] as HTMLElement).offsetHeight -
grid.verticalScrollContainer.getScroll().offsetHeight).toBeLessThanOrEqual(0);
}));
});
describe('Resizing', () => {
const DEBOUNCE_TIME = 200;
const GRID_COL_GROUP_THEAD = 'igx-grid-header-group';
const RESIZE_LINE_CLASS = '.igx-grid-th__resize-line';
beforeEach(() => {
fixture = TestBed.createComponent(ColumnLayoutResizingTestComponent);
fixture.detectChanges();
grid = fixture.componentInstance.grid;
});
it('should correctly resize column on upper level with 3 spans and the two cols below it with span 1 that have width', async () => {
grid.width = '1500px';
fixture.componentInstance.colGroups = [{
group: 'group1',
columns: [
{ field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '300px', resizable: true },
{ field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true },
{ field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true },
{ field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true },
{ field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true },
{ field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true },
{ field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true },
{ field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true },
{ field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 },
]
}];
fixture.detectChanges();
await wait(DEBOUNCE_TIME);
fixture.detectChanges();
// ContactName
expect(grid.columnList.get(1).width).toEqual('300px');
expect(grid.columnList.get(1).cells[0].value).toEqual('Maria Anders');
const headerCells = fixture.debugElement.queryAll(By.css(GRID_COL_GROUP_THEAD));
const headerResArea = headerCells[1].children[1].nativeElement;
UIInteractions.simulateMouseEvent('mousedown', headerResArea, 450, 0);
fixture.detectChanges();
await wait(DEBOUNCE_TIME);
const resizer = fixture.debugElement.queryAll(By.css(RESIZE_LINE_CLASS))[0].nativeElement;
expect(resizer).toBeDefined();
UIInteractions.simulateMouseEvent('mousemove', resizer, 600, 5);
UIInteractions.simulateMouseEvent('mouseup', resizer, 600, 5);
fixture.detectChanges();
const groupRowBlocks = fixture.debugElement.query(By.css('.igx-grid__tbody')).queryAll(By.css(`.${GRID_MRL_BLOCK}`));
expect(groupRowBlocks[0].nativeElement.style.gridTemplateColumns).toEqual('250px 250px 150px 100px 100px 200px');
});
it('should correctly resize column with span 2 and the ones below it that have span 1 with width set', async () => {
grid.width = '1500px';
fixture.componentInstance.colGroups = [{
group: 'group1',
columns: [
{ field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '300px', resizable: true },
{ field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true },
{ field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true },
{ field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true },
{ field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true },
{ field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true },
{ field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true },
{ field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true },
{ field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 },
]
}];
fixture.detectChanges();
await wait(DEBOUNCE_TIME);
fixture.detectChanges();
// Phone
expect(grid.columnList.get(4).width).toEqual('200px');
expect(grid.columnList.get(4).cells[0].value).toEqual('030-0074321');
const headerCells = fixture.debugElement.queryAll(By.css(GRID_COL_GROUP_THEAD));
const headerResArea = headerCells[4].children[1].nativeElement;
UIInteractions.simulateMouseEvent('mousedown', headerResArea, 450, 0);
await wait(DEBOUNCE_TIME);
fixture.detectChanges();
const resizer = fixture.debugElement.queryAll(By.css(RESIZE_LINE_CLASS))[0].nativeElement;
expect(resizer).toBeDefined();
UIInteractions.simulateMouseEvent('mousemove', resizer, 550, 5);
UIInteractions.simulateMouseEvent('mouseup', resizer, 550, 5);
fixture.detectChanges();
const groupRowBlocks = fixture.debugElement.query(By.css('.igx-grid__tbody')).queryAll(By.css(`.${GRID_MRL_BLOCK}`));
expect(groupRowBlocks[0].nativeElement.style.gridTemplateColumns).toEqual('250px 250px 100px 100px 100px 200px');
});
it('should correctly resize column that spans 1 column that is used to size the column templates', async () => {
grid.width = '1500px';
fixture.componentInstance.colGroups = [{
group: 'group1',
columns: [
{ field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '300px', resizable: true },
{ field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true },
{ field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true },
{ field: 'Ph