igniteui-angular-sovn
Version:
Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps
1,045 lines (862 loc) • 169 kB
text/typescript
import { TestBed, fakeAsync, tick, ComponentFixture } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { IgxGridComponent } from './public_api';
import { configureTestSuite } from '../../test-utils/configure-suite';
import {
SelectionWithScrollsComponent,
SelectionWithTransactionsComponent,
CellSelectionNoneComponent,
CellSelectionSingleComponent
} from '../../test-utils/grid-samples.spec';
import { IgxStringFilteringOperand } from '../../data-operations/filtering-condition';
import { UIInteractions, wait } from '../../test-utils/ui-interactions.spec';
import { clearGridSubs, setupGridScrollDetection } from '../../test-utils/helper-utils.spec';
import { GridSelectionMode } from '../common/enums';
import { GridSelectionFunctions, GridFunctions } from '../../test-utils/grid-functions.spec';
import { DefaultSortingStrategy, SortingDirection } from '../../data-operations/sorting-strategy';
import { DebugElement } from '@angular/core';
import { DropPosition } from '../moving/moving.service';
import { IgxGridGroupByRowComponent } from './groupby-row.component';
describe('IgxGrid - Cell selection #grid', () => {
configureTestSuite((() => {
return TestBed.configureTestingModule({
imports: [
NoopAnimationsModule,
SelectionWithScrollsComponent,
SelectionWithTransactionsComponent,
CellSelectionNoneComponent,
CellSelectionSingleComponent
]
});
}));
describe('Base', () => {
let fix;
let grid: IgxGridComponent;
let detect;
beforeEach(() => {
fix = TestBed.createComponent(SelectionWithScrollsComponent);
fix.detectChanges();
grid = fix.componentInstance.grid;
detect = () => grid.cdr.detectChanges();
});
it('Should be able to select a range with mouse dragging', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const startCell = grid.gridAPI.get_cell_by_index(2, 'ParentID');
const endCell = grid.gridAPI.get_cell_by_index(3, 'ID');
const range = { rowStart: 2, rowEnd: 3, columnStart: 0, columnEnd: 1 };
UIInteractions.simulatePointerOverElementEvent('pointerdown', startCell.nativeElement);
detect();
expect(startCell.active).toBe(true);
for (let i = 3; i < 5; i++) {
const cell = grid.gridAPI.get_cell_by_index(i, grid.columnList.get(i - 1).field);
UIInteractions.simulatePointerOverElementEvent('pointerenter', cell.nativeElement);
detect();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, i, 1, i - 1);
}
for (let i = 3; i >= 0; i--) {
const cell = grid.gridAPI.get_cell_by_index(i, 'HireDate');
UIInteractions.simulatePointerOverElementEvent('pointerenter', cell.nativeElement);
detect();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, i, 1, 3);
}
for (let i = 2; i >= 0; i--) {
const cell = grid.gridAPI.get_cell_by_index(0, grid.columnList.get(i).field);
UIInteractions.simulatePointerOverElementEvent('pointerenter', cell.nativeElement);
detect();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, 0, 1, i);
}
for (let i = 1; i < 4; i++) {
const cell = grid.gridAPI.get_cell_by_index(i, 'ID');
UIInteractions.simulatePointerOverElementEvent('pointerenter', cell.nativeElement);
detect();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, i, 1, 0);
}
UIInteractions.simulatePointerOverElementEvent('pointerup', endCell.nativeElement);
detect();
expect(startCell.active).toBe(true);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, 3, 1, 0);
GridSelectionFunctions.verifySelectedRange(grid, 2, 3, 0, 1);
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
expect(selectionChangeSpy).toHaveBeenCalledWith(range);
});
it('Should not lose selection on right clicking', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range = { rowStart: 2, rowEnd: 3, columnStart: 0, columnEnd: 1 };
grid.setSelection(range);
detect();
GridSelectionFunctions.verifySelectedRange(grid, 2, 3, 0, 1, 0, 1);
// Simulate right-click
const endCell = grid.gridAPI.get_cell_by_index(4, 'ID');
UIInteractions.simulateNonPrimaryClick(endCell);
detect();
GridSelectionFunctions.verifySelectedRange(grid, 2, 3, 0, 1, 0, 1);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
const c = grid.gridAPI.get_cell_by_index(0, 'ID');
UIInteractions.simulateClickAndSelectEvent(c);
detect();
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
GridSelectionFunctions.verifySelectedRange(grid, 0, 0, 0, 0, 0, 1);
});
it('Should be able to select multiple ranges with Ctrl key and mouse drag', () => {
let firstCell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
let secondCell = grid.gridAPI.get_cell_by_index(2, 'Name');
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
GridSelectionFunctions.selectCellsRangeNoWait(fix, firstCell, secondCell);
detect();
let range = { rowStart: 1, rowEnd: 2, columnStart: 1, columnEnd: 2 };
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
expect(selectionChangeSpy).toHaveBeenCalledWith(range);
expect(grid.selectedCells.length).toBe(4);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 1, 2);
firstCell = grid.gridAPI.get_cell_by_index(2, 'ParentID');
secondCell = grid.gridAPI.get_cell_by_index(3, 'ID');
GridSelectionFunctions.selectCellsRangeNoWait(fix, firstCell, secondCell, true);
detect();
expect(grid.selectedCells.length).toBe(7);
range = { rowStart: 2, rowEnd: 3, columnStart: 0, columnEnd: 1 };
expect(selectionChangeSpy).toHaveBeenCalledTimes(2);
expect(selectionChangeSpy).toHaveBeenCalledWith(range);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 1, 2);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, 3, 0, 1);
});
it('Should select correct cells with Ctrl key and mouse drag', () => {
const range = { rowStart: 3, rowEnd: 2, columnStart: 'Name', columnEnd: 'ParentID' };
const firstCell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
const secondCell = grid.gridAPI.get_cell_by_index(1, 'ID');
const thirdCell = grid.gridAPI.get_cell_by_index(2, 'ParentID');
const expectedData = [
{ ParentID: 147, Name: 'Monica Reyes' },
{ ParentID: 847, Name: 'Laurence Johnson' },
{ ParentID: 147 }
];
grid.selectRange(range);
fix.detectChanges();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, 3, 1, 2);
GridSelectionFunctions.verifySelectedRange(grid, 2, 3, 1, 2);
UIInteractions.simulatePointerOverElementEvent('pointerdown', firstCell.nativeElement, false, true);
detect();
expect(firstCell.active).toBe(true);
GridSelectionFunctions.verifySelectedRange(grid, 2, 3, 1, 2);
UIInteractions.simulatePointerOverElementEvent('pointerenter', secondCell.nativeElement, false, true);
detect();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, 3, 1, 2);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 1, 0, 1);
GridSelectionFunctions.verifySelectedRange(grid, 2, 3, 1, 2);
UIInteractions.simulatePointerOverElementEvent('pointerenter', thirdCell.nativeElement, false, true);
detect();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, 3, 1, 2);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 1, 1);
GridSelectionFunctions.verifySelectedRange(grid, 2, 3, 1, 2);
UIInteractions.simulatePointerOverElementEvent('pointerup', thirdCell.nativeElement);
detect();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, 3, 1, 2);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 1, 1);
GridSelectionFunctions.verifyCellSelected(secondCell, false);
GridSelectionFunctions.verifySelectedRange(grid, 2, 3, 1, 2, 0, 2);
GridSelectionFunctions.verifySelectedRange(grid, 1, 2, 1, 1, 1, 2);
expect(grid.getSelectedData()).toEqual(expectedData);
});
it('Should be able to select multiple cells with Ctrl key and mouse click', () => {
const firstCell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
const secondCell = grid.gridAPI.get_cell_by_index(2, 'Name');
const thirdCell = grid.gridAPI.get_cell_by_index(0, 'ID');
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
UIInteractions.simulateClickAndSelectEvent(firstCell);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
GridSelectionFunctions.verifyCellSelected(firstCell);
expect(grid.selectedCells.length).toBe(1);
UIInteractions.simulateClickAndSelectEvent(secondCell, false, true);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
GridSelectionFunctions.verifyCellSelected(firstCell);
GridSelectionFunctions.verifyCellSelected(secondCell);
expect(grid.selectedCells.length).toBe(2);
UIInteractions.simulateClickAndSelectEvent(thirdCell, false, true);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
GridSelectionFunctions.verifyCellSelected(firstCell);
GridSelectionFunctions.verifyCellSelected(secondCell);
GridSelectionFunctions.verifyCellSelected(thirdCell);
expect(grid.selectedCells.length).toBe(3);
expect(grid.getSelectedData()).toEqual([{ ParentID: 147 }, { Name: 'Monica Reyes' }, { ID: 475 }]);
GridSelectionFunctions.verifySelectedRange(grid, 1, 1, 1, 1, 0, 3);
GridSelectionFunctions.verifySelectedRange(grid, 2, 2, 2, 2, 1, 3);
GridSelectionFunctions.verifySelectedRange(grid, 0, 0, 0, 0, 2, 3);
});
it('Should be able to select cells correctly when focus is returned to the grid', async() => {
const firstCell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
const secondCell = grid.gridAPI.get_cell_by_index(2, 'Name');
UIInteractions.simulateClickAndSelectEvent(firstCell);
fix.detectChanges();
GridSelectionFunctions.verifyCellSelected(firstCell);
expect(grid.selectedCells.length).toBe(1);
UIInteractions.simulateClickAndSelectEvent(firstCell, false, true);
fix.detectChanges();
expect(grid.selectedCells.length).toBe(0);
grid.navigation.lastActiveNode = grid.navigation.activeNode;
grid.navigation.activeNode = null;
fix.detectChanges();
grid.tbody.nativeElement.focus();
fix.detectChanges();
UIInteractions.simulateClickAndSelectEvent(secondCell, false, true);
fix.detectChanges();
GridSelectionFunctions.verifyCellSelected(firstCell, false);
GridSelectionFunctions.verifyCellSelected(secondCell, true);
expect(grid.selectedCells.length).toBe(1);
});
it('Should be able to select range when click on a cell and hold Shift key and click on another Cell', () => {
const firstCell = grid.gridAPI.get_cell_by_index(3, 'HireDate');
const secondCell = grid.gridAPI.get_cell_by_index(1, 'ID');
const thirdCell = grid.gridAPI.get_cell_by_index(0, 'Name');
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
GridSelectionFunctions.selectCellsRangeWithShiftKeyNoWait(fix, firstCell, secondCell);
expect(grid.selectedCells.length).toBe(12);
let range = { rowStart: 1, rowEnd: 3, columnStart: 0, columnEnd: 3 };
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
expect(selectionChangeSpy).toHaveBeenCalledWith(range);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 3, 0, 3);
GridSelectionFunctions.verifySelectedRange(grid, 1, 3, 0, 3);
UIInteractions.simulateClickAndSelectEvent(thirdCell, true);
fix.detectChanges();
expect(grid.selectedCells.length).toBe(8);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 3, 2, 3);
range = { rowStart: 0, rowEnd: 3, columnStart: 2, columnEnd: 3 };
expect(selectionChangeSpy).toHaveBeenCalledTimes(2);
expect(selectionChangeSpy).toHaveBeenCalledWith(range);
GridSelectionFunctions.verifySelectedRange(grid, 0, 3, 2, 3);
});
it('Should return correct ranges from `getSelectedRanges` on shfit + click in the event handler', () => {
const firstCell = grid.gridAPI.get_cell_by_index(3, 'HireDate');
const secondCell = grid.gridAPI.get_cell_by_index(1, 'ID');
const sub = grid.rangeSelected.subscribe(_ => {
expect(grid.selectedCells.length).toEqual(12);
const range = grid.getSelectedRanges()[0];
GridSelectionFunctions.verifySelectedRange(grid, range.rowStart, range.rowEnd, range.columnStart, range.columnEnd);
GridSelectionFunctions.verifySelectedRange(grid, 1, 3, 0, 3);
});
GridSelectionFunctions.selectCellsRangeWithShiftKeyNoWait(fix, firstCell, secondCell);
sub.unsubscribe();
});
it('Should be able to select range with Shift key when first cell is not visible', (async () => {
const firstCell = grid.gridAPI.get_cell_by_index(1, 'ID');
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const expectedData1 = [
{ ID: 957, ParentID: 147 },
{ ID: 317, ParentID: 147 },
{ ID: 225, ParentID: 847 },
{ ID: 663, ParentID: 847 },
{ ID: 15, ParentID: 19 },
{ ID: 12, ParentID: 17 },
{ ID: 101, ParentID: 17 }
];
const expectedData2 = [
{ ID: 957, ParentID: 147, Name: 'Thomas Hardy' },
{ ID: 317, ParentID: 147, Name: 'Monica Reyes' },
{ ID: 225, ParentID: 847, Name: 'Laurence Johnson' },
{ ID: 663, ParentID: 847, Name: 'Elizabeth Richards' },
{ ID: 15, ParentID: 19, Name: 'Antonio Moreno' },
{ ID: 12, ParentID: 17, Name: 'Pedro Afonso' }
];
UIInteractions.simulateClickAndSelectEvent(firstCell);
await wait();
fix.detectChanges();
GridSelectionFunctions.verifyCellSelected(firstCell);
grid.verticalScrollContainer.scrollTo(grid.dataView.length - 1);
await wait(100);
fix.detectChanges();
const secondCell = grid.gridAPI.get_cell_by_index(7, 'ParentID');
UIInteractions.simulateClickAndSelectEvent(secondCell, true);
await wait();
fix.detectChanges();
let range = { rowStart: 1, rowEnd: 7, columnStart: 0, columnEnd: 1 };
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
expect(grid.getSelectedData()).toEqual(expectedData1);
expect(selectionChangeSpy).toHaveBeenCalledWith(range);
expect(grid.getSelectedRanges()).toEqual([range]);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 3, 7, 0, 1);
const thirdCell = grid.gridAPI.get_cell_by_index(6, 'Name');
UIInteractions.simulateClickAndSelectEvent(thirdCell, true);
await wait();
fix.detectChanges();
range = { rowStart: 1, rowEnd: 6, columnStart: 0, columnEnd: 2 };
expect(selectionChangeSpy).toHaveBeenCalledTimes(2);
expect(selectionChangeSpy).toHaveBeenCalledWith(range);
expect(grid.getSelectedRanges()).toEqual([range]);
expect(grid.getSelectedData()).toEqual(expectedData2);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 3, 6, 0, 2);
grid.verticalScrollContainer.scrollTo(0);
await wait(100);
fix.detectChanges();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 4, 0, 2);
expect(selectionChangeSpy).toHaveBeenCalledTimes(2);
expect(grid.getSelectedData()).toEqual(expectedData2);
}));
it('Should update range selection when hold a Ctrl key and click on another cell', () => {
const firstCell = grid.gridAPI.get_cell_by_index(2, 'ID');
const secondCell = grid.gridAPI.get_cell_by_index(0, 'ParentID');
const thirdCell = grid.gridAPI.get_cell_by_index(0, 'Name');
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const expectedData1 = [
{ ID: 475, ParentID: 147 },
{ ID: 957, ParentID: 147 },
{ ID: 317, ParentID: 147 }
];
const expectedData2 = [
{ ID: 475, ParentID: 147, Name: 'Michael Langdon' },
{ ID: 957 },
{ ID: 317, ParentID: 147 }
];
GridSelectionFunctions.selectCellsRangeWithShiftKeyNoWait(fix, firstCell, secondCell);
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
expect(selectionChangeSpy).toHaveBeenCalledWith({ rowStart: 0, rowEnd: 2, columnStart: 0, columnEnd: 1 });
expect(grid.getSelectedData()).toEqual(expectedData1);
GridSelectionFunctions.verifySelectedRange(grid, 0, 2, 0, 1);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 2, 0, 1);
// Click on another cell holding control
UIInteractions.simulateClickAndSelectEvent(thirdCell, false, true);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
GridSelectionFunctions.verifySelectedRange(grid, 0, 2, 0, 1, 0, 2);
GridSelectionFunctions.verifySelectedRange(grid, 0, 0, 2, 2, 1, 2);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 2, 0, 1);
GridSelectionFunctions.verifyCellSelected(thirdCell);
// Click on a cell in the region and verify it is deselected
let cell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
UIInteractions.simulateClickAndSelectEvent(cell, false, true);
fix.detectChanges();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 0, 0, 2);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, 2, 0, 1);
GridSelectionFunctions.verifyCellSelected(cell, false);
GridSelectionFunctions.verifyCellSelected(grid.gridAPI.get_cell_by_index(1, 'ID'), true);
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
expect(grid.getSelectedData()).toEqual(expectedData2);
// Click on a cell without holding Ctrl
cell = grid.gridAPI.get_cell_by_index(0, 'ID');
UIInteractions.simulateClickAndSelectEvent(cell);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
expect(grid.getSelectedData()).toEqual([{ ID: 475 }]);
GridSelectionFunctions.verifySelectedRange(grid, 0, 0, 0, 0);
GridSelectionFunctions.verifyCellSelected(cell);
GridSelectionFunctions.verifyCellSelected(firstCell, false);
GridSelectionFunctions.verifyCellSelected(secondCell, false);
GridSelectionFunctions.verifyCellSelected(thirdCell, false);
});
it('Should not be possible to select a range when change cellSelection to none', () => {
const rangeChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const startCell = grid.gridAPI.get_cell_by_index(0, 'Name');
const endCell = grid.gridAPI.get_cell_by_index(2, 'ParentID');
expect(grid.cellSelection).toEqual(GridSelectionMode.multiple);
GridSelectionFunctions.selectCellsRangeNoWait(fix, startCell, endCell);
detect();
expect(rangeChangeSpy).toHaveBeenCalledTimes(1);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 2, 1, 2);
GridSelectionFunctions.verifySelectedRange(grid, 0, 2, 1, 2);
grid.cellSelection = GridSelectionMode.none;
fix.detectChanges();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 2, 1, 2, false);
expect(grid.getSelectedData()).toEqual([]);
expect(grid.getSelectedRanges()).toEqual([]);
// Try to select a range
GridSelectionFunctions.selectCellsRangeNoWait(fix, startCell, endCell);
detect();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 2, 1, 2, false);
expect(rangeChangeSpy).toHaveBeenCalledTimes(1);
expect(grid.selectedCells.length).toBe(0);
expect(grid.getSelectedData().length).toBe(1);
expect(grid.getSelectedRanges()).toEqual([]);
});
it('Should not be possible to select a range when change cellSelection to single', () => {
const rangeChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const startCell = grid.gridAPI.get_cell_by_index(0, 'ID');
const endCell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
expect(grid.cellSelection).toEqual(GridSelectionMode.multiple);
GridSelectionFunctions.selectCellsRangeNoWait(fix, startCell, endCell);
detect();
expect(rangeChangeSpy).toHaveBeenCalledTimes(1);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 1, 0, 1);
GridSelectionFunctions.verifySelectedRange(grid, 0, 1, 0, 1);
grid.cellSelection = GridSelectionMode.single;
fix.detectChanges();
expect(grid.cellSelection).toEqual(GridSelectionMode.single);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 1, 0, 1, false);
expect(grid.getSelectedData()).toEqual([]);
expect(grid.getSelectedRanges()).toEqual([]);
// Try to select a range
UIInteractions.simulatePointerOverElementEvent('pointerdown', endCell.nativeElement);
endCell.nativeElement.dispatchEvent(new MouseEvent('click'));
fix.detectChanges();
UIInteractions.simulatePointerOverElementEvent('pointerenter', startCell.nativeElement);
UIInteractions.simulatePointerOverElementEvent('pointerup', startCell.nativeElement);
fix.detectChanges();
detect();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 0, 0, 1, false);
expect(rangeChangeSpy).toHaveBeenCalledTimes(1);
expect(grid.selectedCells.length).toBe(1);
expect(grid.getSelectedData()).toEqual([{ ParentID: 147 }]);
GridSelectionFunctions.verifySelectedRange(grid, 1, 1, 1, 1);
});
});
describe('API', () => {
let fix;
let grid;
let detect;
beforeEach(() => {
fix = TestBed.createComponent(SelectionWithScrollsComponent);
fix.detectChanges();
grid = fix.componentInstance.grid;
detect = () => grid.cdr.detectChanges();
});
it('Should select a single cell', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range = { rowStart: 2, rowEnd: 2, columnStart: 1, columnEnd: 1 };
const cell = grid.gridAPI.get_cell_by_index(2, 'ParentID');
const expectedData = [
{ ParentID: 147 }
];
grid.selectRange(range);
fix.detectChanges();
GridSelectionFunctions.verifyCellSelected(cell);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual(expectedData);
expect(grid.getSelectedRanges()).toEqual([range]);
});
it('Should select a region', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range = { rowStart: 0, rowEnd: 2, columnStart: 'Name', columnEnd: 'ParentID' };
const expectedData = [
{ ParentID: 147, Name: 'Michael Langdon' },
{ ParentID: 147, Name: 'Thomas Hardy' },
{ ParentID: 147, Name: 'Monica Reyes' }
];
grid.selectRange(range);
fix.detectChanges();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 2, 1, 2);
GridSelectionFunctions.verifySelectedRange(grid, 0, 2, 1, 2);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual(expectedData);
});
it('Should select a region when one of cells is not visible', (async () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range = { rowStart: 3, rowEnd: 7, columnStart: 'ID', columnEnd: 'ParentID' };
const expectedData = [
{ ID: 225, ParentID: 847 },
{ ID: 663, ParentID: 847 },
{ ID: 15, ParentID: 19 },
{ ID: 12, ParentID: 17 },
{ ID: 101, ParentID: 17 }
];
grid.selectRange(range);
fix.detectChanges();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 3, 4, 0, 1);
GridSelectionFunctions.verifySelectedRange(grid, 3, 7, 0, 1);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual(expectedData);
grid.verticalScrollContainer.scrollTo(grid.dataView.length - 1);
await wait(100);
fix.detectChanges();
GridSelectionFunctions.verifyCellsRegionSelected(grid, 4, 7, 0, 1);
GridSelectionFunctions.verifySelectedRange(grid, 3, 7, 0, 1);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual(expectedData);
}));
it('Should select a region when two of cells are not visible', (async () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range = { rowStart: 6, rowEnd: 6, columnStart: 'OnPTO', columnEnd: 'Age' };
const expectedData = [
{ Age: 50, OnPTO: false }
];
grid.selectRange(range);
fix.detectChanges();
GridSelectionFunctions.verifySelectedRange(grid, 6, 6, 4, 5);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual(expectedData);
grid.verticalScrollContainer.scrollTo(grid.dataView.length - 1);
await wait(100);
fix.detectChanges();
grid.dataRowList.first.virtDirRow.scrollTo(5);
await wait(100);
fix.detectChanges();
GridSelectionFunctions.verifySelectedRange(grid, 6, 6, 4, 5);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual(expectedData);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 6, 6, 4, 5);
}));
it('Should add new range when there is already added range', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range1 = { rowStart: 0, rowEnd: 1, columnStart: 'ID', columnEnd: 'ParentID' };
const range2 = { rowStart: 1, rowEnd: 2, columnStart: 'ParentID', columnEnd: 'Name' };
const expectedData1 = [
{ ID: 475, ParentID: 147 },
{ ID: 957, ParentID: 147 }
];
const expectedData2 = [
{ ID: 475, ParentID: 147 },
{ ID: 957, ParentID: 147, Name: 'Thomas Hardy' },
{ ParentID: 147, Name: 'Monica Reyes' }
];
grid.selectRange(range1);
fix.detectChanges();
GridSelectionFunctions.verifySelectedRange(grid, 0, 1, 0, 1);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual(expectedData1);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 1, 0, 1);
grid.selectRange(range2);
fix.detectChanges();
GridSelectionFunctions.verifySelectedRange(grid, 0, 1, 0, 1, 0, 2);
GridSelectionFunctions.verifySelectedRange(grid, 1, 2, 1, 2, 1, 2);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual(expectedData2);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 1, 0, 1);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 1, 2);
});
it('Should add multiple ranges', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range1 = { rowStart: 0, rowEnd: 0, columnStart: 'ID', columnEnd: 'ParentID' };
const range2 = { rowStart: 2, rowEnd: 3, columnStart: 'ParentID', columnEnd: 'Name' };
const expectedData = [
{ ID: 475, ParentID: 147 },
{ ParentID: 147, Name: 'Monica Reyes' },
{ ParentID: 847, Name: 'Laurence Johnson' }
];
grid.selectRange([range1, range2]);
fix.detectChanges();
GridSelectionFunctions.verifySelectedRange(grid, 0, 0, 0, 1, 0, 2);
GridSelectionFunctions.verifySelectedRange(grid, 2, 3, 1, 2, 1, 2);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual(expectedData);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 0, 0, 1);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, 3, 1, 2);
});
it('Should add multiple ranges when they have same cells', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range1 = { rowStart: 1, rowEnd: 3, columnStart: 'ID', columnEnd: 'ParentID' };
const range2 = { rowStart: 3, rowEnd: 1, columnStart: 'ParentID', columnEnd: 'ID' };
const expectedData = [
{ ID: 957, ParentID: 147 },
{ ID: 317, ParentID: 147 },
{ ID: 225, ParentID: 847 }
];
grid.selectRange([range1, range2]);
fix.detectChanges();
GridSelectionFunctions.verifySelectedRange(grid, 1, 3, 0, 1);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual(expectedData);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 3, 0, 1);
});
it('Should add multiple ranges when some of their cells are same', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range1 = { rowStart: 1, rowEnd: 3, columnStart: 'ID', columnEnd: 'ParentID' };
const range2 = { rowStart: 4, rowEnd: 2, columnStart: 'ParentID', columnEnd: 'ID' };
const expectedData = [
{ ID: 957, ParentID: 147 },
{ ID: 317, ParentID: 147 },
{ ID: 225, ParentID: 847 },
{ ID: 663, ParentID: 847 }
];
grid.selectRange([range1, range2]);
fix.detectChanges();
GridSelectionFunctions.verifySelectedRange(grid, 1, 3, 0, 1, 0, 2);
GridSelectionFunctions.verifySelectedRange(grid, 2, 4, 0, 1, 1, 2);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual(expectedData);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 4, 0, 1);
});
it('Should not add range when column is hidden', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range = { rowStart: 1, rowEnd: 3, columnStart: 'ID', columnEnd: 'Name' };
grid.getColumnByName('Name').hidden = true;
fix.detectChanges();
let errorMessage = '';
try {
grid.selectRange(range);
} catch (error) {
errorMessage = error.message;
} finally {
fix.detectChanges();
}
expect(errorMessage).toContain('visibleIndex');
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual([]);
expect(grid.getSelectedRanges()).toEqual([]);
});
it('Should not add range when column is hidden and there is already selected range', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range1 = { rowStart: 1, rowEnd: 2, columnStart: 'ID', columnEnd: 'Name' };
const range2 = { rowStart: 0, rowEnd: 4, columnStart: 'ParentID', columnEnd: 'OnPTO' };
const expectedData = [
{ ID: 957, Name: 'Thomas Hardy' },
{ ID: 317, Name: 'Monica Reyes' }
];
grid.getColumnByName('ParentID').hidden = true;
fix.detectChanges();
grid.selectRange(range1);
fix.detectChanges();
GridSelectionFunctions.verifySelectedRange(grid, 1, 2, 0, 1);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual(expectedData);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 0, 1);
let errorMessage = '';
try {
grid.selectRange(range2);
} catch (error) {
errorMessage = error.message;
} finally {
fix.detectChanges();
}
expect(errorMessage).toContain('visibleIndex');
GridSelectionFunctions.verifySelectedRange(grid, 1, 2, 0, 1);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual(expectedData);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 0, 1);
});
it('Should not add range when column does not exist', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range = { rowStart: 1, rowEnd: 3, columnStart: 'NotExisting', columnEnd: 'Name' };
let errorMessage = '';
try {
grid.selectRange(range);
} catch (error) {
errorMessage = error.message;
} finally {
fix.detectChanges();
}
expect(errorMessage).toContain('visibleIndex');
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedData()).toEqual([]);
expect(grid.getSelectedRanges()).toEqual([]);
});
it('Should add range when row does not exist', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range = { rowStart: -7, rowEnd: 100, columnStart: 'ID', columnEnd: 'ID' };
const expectedData = [
{ ID: 475 },
{ ID: 957 },
{ ID: 317 },
{ ID: 225 },
{ ID: 663 },
{ ID: 15 },
{ ID: 12 },
{ ID: 101 }
];
grid.selectRange(range);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
GridSelectionFunctions.verifySelectedRange(grid, -7, 100, 0, 0);
expect(grid.getSelectedData()).toEqual(expectedData);
});
it('Should add range when columnStart index does not exist', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range = { rowStart: 0, rowEnd: 1, columnStart: -4, columnEnd: 0 };
const expectedData = [
{ ID: 475 },
{ ID: 957 }
];
grid.selectRange(range);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
GridSelectionFunctions.verifySelectedRange(grid, 0, 1, -4, 0);
expect(grid.getSelectedData()).toEqual(expectedData);
});
it('Should add range when columnStart and columnEnd indexes do not exist', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range = { rowStart: 1, rowEnd: 2, columnStart: 5, columnEnd: 10 };
const expectedData = [
{ OnPTO: true },
{ OnPTO: false }
];
grid.selectRange(range);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
GridSelectionFunctions.verifySelectedRange(grid, 1, 2, 5, 10);
expect(grid.getSelectedData()).toEqual(expectedData);
});
it('Should not add range when columnStart and columnEnd indexes do not exist', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range = { rowStart: 1, rowEnd: 2, columnStart: 10, columnEnd: 100 };
grid.selectRange(range);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
GridSelectionFunctions.verifySelectedRange(grid, 1, 2, 10, 100);
expect(grid.getSelectedData()).toEqual([]);
});
it('Should be able to clear the selected ranges', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const range = { rowStart: 1, rowEnd: 2, columnStart: 1, columnEnd: 2 };
const expectedData = [
{ ParentID: 147, Name: 'Thomas Hardy' },
{ ParentID: 147, Name: 'Monica Reyes' }
];
grid.selectRange(range);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
GridSelectionFunctions.verifySelectedRange(grid, 1, 2, 1, 2);
expect(grid.getSelectedData()).toEqual(expectedData);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 1, 2);
grid.selectRange();
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
expect(grid.getSelectedRanges().length).toEqual(0);
expect(grid.getSelectedData()).toEqual([]);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 1, 2, false);
});
it('Should be able to clear the selection when a single cell is selected', () => {
const cell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
UIInteractions.simulateClickAndSelectEvent(cell);
fix.detectChanges();
GridSelectionFunctions.verifyCellSelected(cell);
GridSelectionFunctions.verifySelectedRange(grid, 1, 1, 1, 1);
grid.selectRange(null);
fix.detectChanges();
expect(grid.getSelectedRanges().length).toEqual(0);
expect(grid.getSelectedData()).toEqual([]);
GridSelectionFunctions.verifyCellSelected(cell, false);
});
it('Should be able to clear the selection when there are no selected cells', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
grid.selectRange();
fix.detectChanges();
expect(grid.getSelectedRanges().length).toEqual(0);
expect(grid.getSelectedData()).toEqual([]);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
});
it('Should return correct selected data when selected event is emitted', () => {
let selectedData = [];
grid.selected.subscribe(() => {
selectedData = grid.getSelectedData();
});
const cell = grid.gridAPI.get_cell_by_index(2, 'Name');
UIInteractions.simulateClickAndSelectEvent(cell);
fix.detectChanges();
expect(selectedData.length).toBe(1);
expect(selectedData[0]).toEqual({ Name: 'Monica Reyes' });
const idCell = grid.gridAPI.get_cell_by_index(1, 'ID');
UIInteractions.simulateClickAndSelectEvent(idCell, false, true);
fix.detectChanges();
expect(selectedData.length).toBe(2);
expect(selectedData[0]).toEqual({ Name: 'Monica Reyes' });
expect(selectedData[1]).toEqual({ ID: 957 });
});
it('rangeSelected event should be emitted when pointer leaves active state outside grid\'s cells', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
const startCell = grid.gridAPI.get_cell_by_index(2, 'ParentID');
const range = { rowStart: 2, rowEnd: 3, columnStart: 0, columnEnd: 1 };
UIInteractions.simulatePointerOverElementEvent('pointerdown', startCell.nativeElement);
detect();
expect(startCell.active).toBe(true);
for (let i = 3; i < 5; i++) {
const cell = grid.gridAPI.get_cell_by_index(i, grid.columnList.get(i - 1).field);
UIInteractions.simulatePointerOverElementEvent('pointerenter', cell.nativeElement);
}
for (let i = 3; i >= 0; i--) {
const cell = grid.gridAPI.get_cell_by_index(i, 'HireDate');
UIInteractions.simulatePointerOverElementEvent('pointerenter', cell.nativeElement);
}
for (let i = 2; i >= 0; i--) {
const cell = grid.gridAPI.get_cell_by_index(0, grid.columnList.get(i).field);
UIInteractions.simulatePointerOverElementEvent('pointerenter', cell.nativeElement);
}
for (let i = 1; i < 4; i++) {
const cell = grid.gridAPI.get_cell_by_index(i, 'ID');
UIInteractions.simulatePointerOverElementEvent('pointerenter', cell.nativeElement);
}
UIInteractions.simulatePointerOverElementEvent('pointerup', document.body);
detect();
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
expect(selectionChangeSpy).toHaveBeenCalledWith(range);
});
it('Should not throw an error when trying to do a drag selection that is started outside the grid', fakeAsync(() => {
const cell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
UIInteractions.simulatePointerOverElementEvent('pointerdown', document.body);
tick();
fix.detectChanges();
UIInteractions.simulatePointerOverElementEvent('pointerenter', cell.nativeElement);
UIInteractions.simulatePointerOverElementEvent('pointerup', cell.nativeElement);
tick();
fix.detectChanges();
expect(() => {
fix.detectChanges();
}).not.toThrow();
}));
});
describe('Keyboard navigation', () => {
let fix: ComponentFixture<any>;
let grid;
let detect;
let gridContent: DebugElement;
beforeEach(() => {
fix = TestBed.createComponent(SelectionWithScrollsComponent);
fix.detectChanges();
grid = fix.componentInstance.grid;
gridContent = GridFunctions.getGridContent(fix);
setupGridScrollDetection(fix, grid);
detect = () => grid.cdr.detectChanges();
});
afterEach(() => {
clearGridSubs();
});
it('Should be able to select a range with arrow keys and holding Shift', () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
let cell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
UIInteractions.simulateClickAndSelectEvent(cell);
fix.detectChanges();
GridSelectionFunctions.verifyCellSelected(cell);
GridSelectionFunctions.verifySelectedRange(grid, 1, 1, 1, 1);
UIInteractions.triggerKeyDownEvtUponElem('arrowdown', cell.nativeElement, true, false, true);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 1, 1);
cell = grid.gridAPI.get_cell_by_index(2, 'ParentID');
UIInteractions.triggerKeyDownEvtUponElem('arrowright', cell.nativeElement, true, false, true);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(2);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 1, 2);
cell = grid.gridAPI.get_cell_by_index(2, 'Name');
UIInteractions.triggerKeyDownEvtUponElem('arrowup', cell.nativeElement, true, false, true);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(3);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 1, 1, 2);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, 2, 1, 3, false);
cell = grid.gridAPI.get_cell_by_index(1, 'Name');
UIInteractions.triggerKeyDownEvtUponElem('arrowleft', cell.nativeElement, true, false, true);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(4);
GridSelectionFunctions.verifyCellSelected(cell, false);
cell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
GridSelectionFunctions.verifyCellSelected(cell);
UIInteractions.triggerKeyDownEvtUponElem('arrowleft', cell.nativeElement, true, false, true);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(5);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 1, 0, 1);
GridSelectionFunctions.verifySelectedRange(grid, 1, 1, 0, 1);
expect(grid.getSelectedData()).toEqual([{ ID: 957, ParentID: 147 }]);
});
it(`Should not clear selection from keyboard shift-state on non-primary click`, () => {
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
let cell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
UIInteractions.simulateClickAndSelectEvent(cell);
fix.detectChanges();
GridSelectionFunctions.verifyCellSelected(cell);
GridSelectionFunctions.verifySelectedRange(grid, 1, 1, 1, 1);
UIInteractions.triggerEventHandlerKeyDown('arrowdown', gridContent, false, true);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 1, 1);
cell = grid.gridAPI.get_cell_by_index(2, 'ParentID');
UIInteractions.triggerEventHandlerKeyDown('arrowright', gridContent, false, true);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(2);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 1, 2);
UIInteractions.simulateNonPrimaryClick(cell);
fix.detectChanges();
expect(selectionChangeSpy).toHaveBeenCalledTimes(2);
GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 1, 2);
});
it(`Should not clear range when try to navigate out the grid with shift
+ arrrow keys and then click on other cell with pressed Ctrl'`, () => {
pending('# Issue should be fixedy');
let cell = grid.gridAPI.get_cell_by_index(0, 'ID');
UIInteractions.simulateClickAndSelectEvent(cell);
fix.detectChanges();
GridSelectionFunctions.