Skip to content

Commit 001d306

Browse files
committed
test(grids): add zoneless regression coverage
1 parent ab6bccc commit 001d306

8 files changed

Lines changed: 395 additions & 10 deletions

File tree

projects/igniteui-angular/grids/grid/src/column.spec.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, DebugElement, TemplateRef, ViewChild, ChangeDetectionStrategy } from '@angular/core';
1+
import { Component, DebugElement, TemplateRef, ViewChild, ChangeDetectionStrategy, provideZonelessChangeDetection } from '@angular/core';
22
import { TestBed, fakeAsync, tick, waitForAsync, ComponentFixture } from '@angular/core/testing';
33
import { By } from '@angular/platform-browser';
44
import { getLocaleCurrencySymbol, registerLocaleData } from '@angular/common';
@@ -1942,3 +1942,30 @@ export class DOMAttributesAsSettersComponent {
19421942

19431943
public data = [{ id: 1, value: 1 }];
19441944
}
1945+
1946+
describe('IgxGrid column autosizing in zoneless change detection #grid', () => {
1947+
beforeEach(() => {
1948+
TestBed.configureTestingModule({
1949+
imports: [ResizableColumnsComponent, NoopAnimationsModule],
1950+
providers: [provideZonelessChangeDetection()]
1951+
});
1952+
});
1953+
1954+
it('should recalculate fit-content widths after data changes', async () => {
1955+
const fix = TestBed.createComponent(ResizableColumnsComponent);
1956+
fix.detectChanges();
1957+
await fix.whenStable();
1958+
const grid = fix.componentInstance.instance;
1959+
1960+
grid.data = [{
1961+
ID: 'VeryVeryVeryLongID',
1962+
Address: 'Avda. de la Constituci\u00f3n 2222 Obere Str. 57'
1963+
}];
1964+
await fix.whenStable();
1965+
grid.recalculateAutoSizes();
1966+
await fix.whenStable();
1967+
1968+
expect(grid.columns[0].width).toBe('164px');
1969+
expect(grid.columns[1].width).toBe('279px');
1970+
});
1971+
});

projects/igniteui-angular/grids/grid/src/grid-cell-selection.spec.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import { clearGridSubs, setupGridScrollDetection } from '../../../test-utils/hel
1414
import { GridSelectionMode } from 'igniteui-angular/grids/core';
1515

1616
import { GridSelectionFunctions, GridFunctions } from '../../../test-utils/grid-functions.spec';
17-
import { DebugElement } from '@angular/core';
17+
import { DebugElement, provideZonelessChangeDetection } from '@angular/core';
18+
import { firstValueFrom } from 'rxjs';
1819
import { DropPosition } from 'igniteui-angular/grids/core';
1920
import { IgxGridGroupByRowComponent } from './groupby-row.component';
2021
import { DefaultSortingStrategy, IgxStringFilteringOperand, SortingDirection } from 'igniteui-angular/core';
@@ -1736,6 +1737,44 @@ describe('IgxGrid - Cell selection #grid', () => {
17361737
}));
17371738
});
17381739

1740+
describe('Keyboard navigation in zoneless change detection', () => {
1741+
let fix: ComponentFixture<SelectionWithScrollsComponent>;
1742+
let grid;
1743+
1744+
beforeEach(() => {
1745+
TestBed.configureTestingModule({
1746+
providers: [
1747+
provideZonelessChangeDetection(),
1748+
{ provide: SCROLL_THROTTLE_TIME_MULTIPLIER, useValue: 0 }
1749+
]
1750+
});
1751+
fix = TestBed.createComponent(SelectionWithScrollsComponent);
1752+
fix.detectChanges();
1753+
grid = fix.componentInstance.grid;
1754+
});
1755+
1756+
it('Should handle Shift + Ctrl + End keys combination', async () => {
1757+
const firstCell = grid.gridAPI.get_cell_by_index(2, 'ID');
1758+
const selectionChangeSpy = spyOn<any>(grid.rangeSelected, 'emit').and.callThrough();
1759+
1760+
UIInteractions.simulateClickAndSelectEvent(firstCell);
1761+
await fix.whenStable();
1762+
1763+
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
1764+
GridSelectionFunctions.verifyCellSelected(firstCell);
1765+
expect(grid.selectedCells.length).toBe(1);
1766+
1767+
const rangeSelected = firstValueFrom(grid.rangeSelected);
1768+
UIInteractions.triggerKeyDownEvtUponElem('end', firstCell.nativeElement, true, false, true, true);
1769+
await rangeSelected;
1770+
await fix.whenStable();
1771+
1772+
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
1773+
GridSelectionFunctions.verifySelectedRange(grid, 2, 7, 0, 5);
1774+
GridSelectionFunctions.verifyCellsRegionSelected(grid, 3, 7, 2, 5);
1775+
});
1776+
});
1777+
17391778
describe('Features integration', () => {
17401779
let fix;
17411780
let grid;

projects/igniteui-angular/grids/grid/src/grid.component.spec.ts

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { AfterViewInit, ChangeDetectorRef, Component, Injectable, OnInit, ViewChild, TemplateRef, inject, ChangeDetectionStrategy } from '@angular/core';
1+
import { AfterViewInit, ChangeDetectorRef, Component, Injectable, OnInit, ViewChild, TemplateRef, inject, ChangeDetectionStrategy, provideZonelessChangeDetection } from '@angular/core';
22
import { TestBed, fakeAsync, tick, flush, waitForAsync } from '@angular/core/testing';
3-
import { BehaviorSubject, Observable } from 'rxjs';
3+
import { BehaviorSubject, firstValueFrom, Observable } from 'rxjs';
44
import { By } from '@angular/platform-browser';
55
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
66
import { IgxGridComponent } from './grid.component';
@@ -2105,6 +2105,63 @@ describe('IgxGrid Component Tests #grid', () => {
21052105
expect(cell.nativeElement.getAttribute('aria-rowindex')).toBe('52');
21062106
expect(cell.nativeElement.getAttribute('aria-colindex')).toBe('17');
21072107
});
2108+
2109+
describe('Zoneless rendering regressions', () => {
2110+
beforeEach(() => {
2111+
TestBed.configureTestingModule({
2112+
imports: [ZonelessTallGridComponent, ZonelessFinJsGridComponent],
2113+
providers: [
2114+
provideZonelessChangeDetection(),
2115+
{ provide: SCROLL_THROTTLE_TIME_MULTIPLIER, useValue: 0 }
2116+
]
2117+
});
2118+
});
2119+
2120+
it('should fully display the last row after scrolling to the bottom', async () => {
2121+
const fix = TestBed.createComponent(ZonelessTallGridComponent);
2122+
fix.detectChanges();
2123+
await fix.whenStable();
2124+
const grid = fix.componentInstance.grid;
2125+
const chunkLoad = firstValueFrom(grid.verticalScrollContainer.chunkLoad);
2126+
2127+
grid.verticalScrollContainer.scrollTo(fix.componentInstance.data.length - 1);
2128+
await chunkLoad;
2129+
await fix.whenStable();
2130+
2131+
const lastRow = grid.gridAPI.get_row_by_index(fix.componentInstance.data.length - 1);
2132+
const rowRect = lastRow.nativeElement.getBoundingClientRect();
2133+
const viewportRect = grid.tbody.nativeElement.getBoundingClientRect();
2134+
expect(rowRect.bottom).toBeLessThanOrEqual(viewportRect.bottom + 1);
2135+
expect(Math.abs(viewportRect.bottom - rowRect.bottom)).toBeLessThanOrEqual(1);
2136+
});
2137+
2138+
it('should stabilize aria-colcount when grouped columns are hidden', async () => {
2139+
const fix = TestBed.createComponent(ZonelessFinJsGridComponent);
2140+
fix.detectChanges();
2141+
await fix.whenStable();
2142+
const grid = fix.componentInstance.grid;
2143+
2144+
expect(grid.nativeElement.getAttribute('aria-colcount')).toBe('48');
2145+
expect(grid.columns.length).toBe(51);
2146+
expect(grid.visibleColumns.length).toBe(48);
2147+
});
2148+
2149+
it('should update horizontal virtualization after a real scroll event', async () => {
2150+
const fix = TestBed.createComponent(ZonelessFinJsGridComponent);
2151+
fix.detectChanges();
2152+
await fix.whenStable();
2153+
const grid = fix.componentInstance.grid;
2154+
const chunkLoad = firstValueFrom(grid.parentVirtDir.chunkLoad);
2155+
const horizontalScroller = grid.headerContainer.getScroll();
2156+
2157+
horizontalScroller.scrollLeft = horizontalScroller.scrollWidth;
2158+
horizontalScroller.dispatchEvent(new Event('scroll'));
2159+
await chunkLoad;
2160+
await fix.whenStable();
2161+
2162+
expect(grid.headerContainer.state.startIndex).toBeGreaterThan(0);
2163+
});
2164+
});
21082165
});
21092166

21102167
describe('IgxGrid - min/max width constraints rules', () => {
@@ -3461,6 +3518,42 @@ export class IgxGridDefaultRenderingComponent {
34613518
}
34623519
}
34633520

3521+
@Component({
3522+
template: `<igx-grid #grid [data]="data" height="300px" width="600px" [autoGenerate]="true"></igx-grid>`,
3523+
imports: [IgxGridComponent]
3524+
})
3525+
class ZonelessTallGridComponent {
3526+
@ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent;
3527+
public data = Array.from({ length: 200 }, (_row, index) => ({
3528+
ID: index,
3529+
Name: `Record ${index}`,
3530+
Value: index * 10
3531+
}));
3532+
}
3533+
3534+
@Component({
3535+
template: `
3536+
<igx-grid #grid [data]="data" height="500px" width="900px"
3537+
[groupingExpressions]="groupingExpressions" [hideGroupedColumns]="true">
3538+
@for (column of columns; track column) {
3539+
<igx-column [field]="column"></igx-column>
3540+
}
3541+
</igx-grid>
3542+
`,
3543+
imports: [IgxGridComponent, IgxColumnComponent]
3544+
})
3545+
class ZonelessFinJsGridComponent {
3546+
@ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent;
3547+
public columns = Array.from({ length: 51 }, (_column, index) => `Column${index}`);
3548+
public groupingExpressions: ISortingExpression[] = this.columns.slice(0, 3).map(fieldName => ({
3549+
fieldName,
3550+
dir: SortingDirection.Asc,
3551+
ignoreCase: true
3552+
}));
3553+
public data = Array.from({ length: 1000 }, (_row, rowIndex) =>
3554+
Object.fromEntries(this.columns.map((column, columnIndex) => [column, `${rowIndex}-${columnIndex}`])));
3555+
}
3556+
34643557
@Component({
34653558
template: `
34663559
<div [hidden]="gridContainerHidden">

projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, ViewChild, TemplateRef, QueryList, ChangeDetectionStrategy } from '@angular/core';
1+
import { Component, ViewChild, TemplateRef, QueryList, ChangeDetectionStrategy, provideZonelessChangeDetection } from '@angular/core';
22
import { formatNumber } from '@angular/common'
33
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
44
import { By } from '@angular/platform-browser';
@@ -20,6 +20,7 @@ import { DefaultSortingStrategy, IGroupingExpression, IgxGrouping, IgxStringFilt
2020
import { IgxChipComponent } from 'igniteui-angular/chips';
2121
import { IgxPaginatorComponent } from 'igniteui-angular/paginator';
2222
import { IgxCheckboxComponent } from 'igniteui-angular/checkbox';
23+
import { firstValueFrom } from 'rxjs';
2324

2425
describe('IgxGrid - GroupBy #grid', () => {
2526

@@ -4392,3 +4393,48 @@ export class GridGroupByStateComponent extends GridGroupByTestDateTimeDataCompon
43924393
@ViewChild(IgxGridStateDirective, { static: true })
43934394
public state: IgxGridStateDirective;
43944395
}
4396+
4397+
describe('IgxGrid grouped virtualization in zoneless change detection #grid', () => {
4398+
beforeEach(() => {
4399+
TestBed.configureTestingModule({
4400+
imports: [GroupableGridComponent, NoopAnimationsModule],
4401+
providers: [provideZonelessChangeDetection()]
4402+
});
4403+
});
4404+
4405+
it('should restore horizontal state when data row views are reused from cache', async () => {
4406+
const fix = TestBed.createComponent(GroupableGridComponent);
4407+
fix.detectChanges();
4408+
await fix.whenStable();
4409+
const grid = fix.componentInstance.instance;
4410+
4411+
grid.groupBy({ fieldName: 'ProductName', dir: SortingDirection.Asc, ignoreCase: false });
4412+
await fix.whenStable();
4413+
grid.toggleAllGroupRows();
4414+
await fix.whenStable();
4415+
4416+
const horizontalChunkLoad = firstValueFrom(grid.parentVirtDir.chunkLoad);
4417+
const horizontalScroller = grid.headerContainer.getScroll();
4418+
horizontalScroller.scrollLeft = 1000;
4419+
horizontalScroller.dispatchEvent(new Event('scroll'));
4420+
await horizontalChunkLoad;
4421+
await fix.whenStable();
4422+
4423+
const scrollLeft = horizontalScroller.scrollLeft;
4424+
grid.toggleAllGroupRows();
4425+
await fix.whenStable();
4426+
4427+
const verticalChunkLoad = firstValueFrom(grid.verticalScrollContainer.chunkLoad);
4428+
grid.verticalScrollContainer.scrollTo(grid.dataView.length - 1);
4429+
await verticalChunkLoad;
4430+
await fix.whenStable();
4431+
4432+
for (const row of grid.dataRowList) {
4433+
const virtualization = row.virtDirRow;
4434+
const expectedStartIndex = virtualization.igxForOf.length - virtualization.state.chunkSize;
4435+
const left = parseFloat(virtualization.dc.instance._viewContainer.element.nativeElement.style.left);
4436+
expect(virtualization.state.startIndex).toBe(expectedStartIndex);
4437+
expect(-left).toBe(scrollLeft - virtualization.getColumnScrollLeft(expectedStartIndex));
4438+
}
4439+
});
4440+
});

projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.navigation.spec.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { TestBed, waitForAsync } from '@angular/core/testing';
22
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
3-
import { Component, ViewChild, DebugElement, ChangeDetectionStrategy } from '@angular/core';
3+
import { Component, ViewChild, DebugElement, ChangeDetectionStrategy, provideZonelessChangeDetection } from '@angular/core';
44
import { IgxChildGridRowComponent, IgxHierarchicalGridComponent } from './hierarchical-grid.component';
55
import { wait, UIInteractions, waitForSelectionChange } from '../../../test-utils/ui-interactions.spec';
66
import { IgxRowIslandComponent } from './row-island.component';
@@ -1035,6 +1035,38 @@ describe('IgxHierarchicalGrid Navigation', () => {
10351035
expect(childGridNested.getBoundingClientRect().bottom <= parentBottom && childGridNested.getBoundingClientRect().top >= parentTop);
10361036
});
10371037
});
1038+
describe('IgxHierarchicalGrid Basic Navigation in zoneless change detection #hGrid', () => {
1039+
beforeEach(waitForAsync(() => {
1040+
TestBed.configureTestingModule({
1041+
providers: [
1042+
provideZonelessChangeDetection(),
1043+
{ provide: SCROLL_THROTTLE_TIME_MULTIPLIER, useValue: 0 }
1044+
]
1045+
});
1046+
fixture = TestBed.createComponent(IgxHierarchicalGridTestBaseComponent);
1047+
fixture.detectChanges();
1048+
hierarchicalGrid = fixture.componentInstance.hgrid;
1049+
}));
1050+
1051+
it('should activate the target cell after Ctrl + End scrolls a child grid', async () => {
1052+
const childGrid = hierarchicalGrid.gridAPI.getChildGrids(false)[0];
1053+
const childCell = childGrid.dataRowList.toArray()[0].cells.toArray()[0];
1054+
GridFunctions.focusCell(fixture, childCell);
1055+
await fixture.whenStable();
1056+
1057+
const activeNodeChange = firstValueFrom(childGrid.activeNodeChange);
1058+
const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1];
1059+
UIInteractions.triggerEventHandlerKeyDown('end', childGridContent, false, false, true);
1060+
await activeNodeChange;
1061+
await fixture.whenStable();
1062+
1063+
const selectedCell = fixture.componentInstance.selectedCell;
1064+
expect(selectedCell.row.index).toEqual(9);
1065+
expect(selectedCell.column.field).toMatch('childData2');
1066+
expect(hierarchicalGrid.verticalScrollContainer.getScroll().scrollTop)
1067+
.toBeGreaterThanOrEqual(childGrid.rowHeight * 5);
1068+
});
1069+
});
10381070
});
10391071

10401072

0 commit comments

Comments
 (0)